diff --git a/pandora/clip/models.py b/pandora/clip/models.py
index e66408a7..8ae0cd11 100644
--- a/pandora/clip/models.py
+++ b/pandora/clip/models.py
@@ -190,12 +190,6 @@ 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")
diff --git a/pandora/document/models.py b/pandora/document/models.py
index 326b9387..30006ecc 100644
--- a/pandora/document/models.py
+++ b/pandora/document/models.py
@@ -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).convert('RGB').crop(crop)
+ img = Image.open(src).crop(crop)
img.save(path)
else:
img = Image.open(path)
diff --git a/pandora/document/views.py b/pandora/document/views.py
index 112f1595..47bf5bd8 100644
--- a/pandora/document/views.py
+++ b/pandora/document/views.py
@@ -12,10 +12,9 @@ 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.conf import settings
from django.db.models import Count, Sum
+from django.conf import settings
from django.http import HttpResponse
-from django.shortcuts import render
from item import utils
from item.models import Item
@@ -513,33 +512,3 @@ 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)
diff --git a/pandora/mobile/__init__.py b/pandora/mobile/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/pandora/mobile/admin.py b/pandora/mobile/admin.py
deleted file mode 100644
index 8c38f3f3..00000000
--- a/pandora/mobile/admin.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.contrib import admin
-
-# Register your models here.
diff --git a/pandora/mobile/apps.py b/pandora/mobile/apps.py
deleted file mode 100644
index 13970a58..00000000
--- a/pandora/mobile/apps.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from django.apps import AppConfig
-
-
-class MobileConfig(AppConfig):
- name = 'mobile'
diff --git a/pandora/mobile/migrations/__init__.py b/pandora/mobile/migrations/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/pandora/mobile/models.py b/pandora/mobile/models.py
deleted file mode 100644
index 71a83623..00000000
--- a/pandora/mobile/models.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.db import models
-
-# Create your models here.
diff --git a/pandora/mobile/tests.py b/pandora/mobile/tests.py
deleted file mode 100644
index 7ce503c2..00000000
--- a/pandora/mobile/tests.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.test import TestCase
-
-# Create your tests here.
diff --git a/pandora/mobile/views.py b/pandora/mobile/views.py
deleted file mode 100644
index fbc0f44c..00000000
--- a/pandora/mobile/views.py
+++ /dev/null
@@ -1,75 +0,0 @@
-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)
diff --git a/pandora/settings.py b/pandora/settings.py
index eae5c942..f6fba9f7 100644
--- a/pandora/settings.py
+++ b/pandora/settings.py
@@ -67,8 +67,7 @@ STATICFILES_DIRS = (
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
- "sass_processor.finders.CssFinder",
- "compressor.finders.CompressorFinder",
+ #'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
GEOIP_PATH = normpath(join(PROJECT_ROOT, '..', 'data', 'geo'))
@@ -125,9 +124,6 @@ INSTALLED_APPS = (
'django_extensions',
'django_celery_results',
'django_celery_beat',
- 'compressor',
- 'sass_processor',
-
'app',
'log',
'annotation',
@@ -154,7 +150,6 @@ INSTALLED_APPS = (
'websocket',
'taskqueue',
'home',
- 'mobile',
)
AUTH_USER_MODEL = 'system.User'
diff --git a/pandora/templates/document.html b/pandora/templates/document.html
deleted file mode 100644
index c893d363..00000000
--- a/pandora/templates/document.html
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-
- {{head_title}}
-
- {% include "baseheader.html" %}
-
- {%if description %} {%endif%}
-
-
-
-
-
-
- {%if description %}{%endif%}
-
-
-
-
-
-
diff --git a/pandora/templates/item.html b/pandora/templates/item.html
index 20a84eb7..6b6e22fd 100644
--- a/pandora/templates/item.html
+++ b/pandora/templates/item.html
@@ -22,7 +22,7 @@

-
+
{{title}}
{{description_html|safe}}
{% for c in clips %}
diff --git a/pandora/templates/mobile/index.html b/pandora/templates/mobile/index.html
deleted file mode 100644
index 5cda3d82..00000000
--- a/pandora/templates/mobile/index.html
+++ /dev/null
@@ -1,45 +0,0 @@
-{% load static sass_tags compress %}
-
-
-
-
- {% if title %}
-
{{title}}
-
-
- {% endif %}
- {%if description %}
-
-
- {%endif%}
- {% if preview %}
-
-
-
- {% endif %}
- {% if url %}
-
- {% endif %}
-
- {% compress css file m %}
-
-
- {% endcompress %}
-
-
-
-
- {% compress js file m %}
-
-
-
-
-
-
-
-
-
-
- {% endcompress %}
-
-
diff --git a/pandora/urls.py b/pandora/urls.py
index 36af1aa0..d8eba049 100644
--- a/pandora/urls.py
+++ b/pandora/urls.py
@@ -26,7 +26,6 @@ import edit.views
import itemlist.views
import item.views
import item.site
-import mobile.views
import translation.views
import urlalias.views
@@ -48,7 +47,6 @@ urlpatterns = [
re_path(r'^collection/(?P
.*?)/icon(?P\d*).jpg$', documentcollection.views.icon),
re_path(r'^documents/(?P[A-Z0-9]+)/(?P\d*)p(?P[\d,]*).jpg$', document.views.thumbnail),
re_path(r'^documents/(?P[A-Z0-9]+)/(?P.*?\.[^\d]{3})$', document.views.file),
- re_path(r'^documents/(?P.*?)$', document.views.document),
re_path(r'^edit/(?P.*?)/icon(?P\d*).jpg$', edit.views.icon),
re_path(r'^list/(?P.*?)/icon(?P\d*).jpg$', itemlist.views.icon),
re_path(r'^text/(?P.*?)/icon(?P\d*).jpg$', text.views.icon),
@@ -67,7 +65,6 @@ urlpatterns = [
re_path(r'^robots.txt$', app.views.robots_txt),
re_path(r'^sitemap.xml$', item.views.sitemap_xml),
re_path(r'^sitemap(?P\d+).xml$', item.views.sitemap_part_xml),
- re_path(r'm/(?P.*?)$', mobile.views.index),
path(r'', item.site.urls),
]
#sould this not be enabled by default? nginx should handle those
diff --git a/requirements.txt b/requirements.txt
index 737f77ce..66f20ff0 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,9 +5,6 @@ celery<5.0,>4.3
django-celery-results<2
django-celery-beat
django-extensions==2.2.9
-libsass
-django-compressor
-django-sass-processor
gunicorn==20.0.4
html5lib
requests<3.0.0,>=2.24.0
diff --git a/static/js/mainMenu.js b/static/js/mainMenu.js
index 457f168d..a7906d8a 100644
--- a/static/js/mainMenu.js
+++ b/static/js/mainMenu.js
@@ -609,8 +609,6 @@ pandora.ui.mainMenu = function() {
pandora.$ui.player.options({fullscreen: true});
} else if (data.id == 'embed') {
pandora.$ui.embedDialog = pandora.ui.embedDialog().open();
- } else if (data.id == 'share') {
- pandora.$ui.shareDialog = pandora.ui.shareDialog().open();
} else if (data.id == 'advancedfind') {
pandora.$ui.filterDialog = pandora.ui.filterDialog().open();
} else if (data.id == 'clearquery') {
@@ -1911,8 +1909,7 @@ pandora.ui.mainMenu = function() {
}) }
] },
{},
- { id: 'embed', title: Ox._('Embed...') },
- { id: 'share', title: Ox._('Share...') }
+ { id: 'embed', title: Ox._('Embed...') }
]}
}
diff --git a/static/js/shareDialog.js b/static/js/shareDialog.js
deleted file mode 100644
index cf399f2b..00000000
--- a/static/js/shareDialog.js
+++ /dev/null
@@ -1,37 +0,0 @@
-'use strict';
-
-pandora.ui.shareDialog = function(/*[url, ]callback*/) {
-
- if (arguments.length == 1) {
- var url, callback = arguments[0];
- } else {
- var url = arguments[0], callback = arguments[1];
- }
- var url = document.location.href.replace(document.location.hostname, document.location.hostname + '/m'),
- $content = Ox.Element().append(
- Ox.Input({
- height: 100,
- width: 256,
- placeholder: 'Share Link',
- type: 'textarea',
- disabled: true,
- value: url
- })
- ),
- that = pandora.ui.iconDialog({
- buttons: [
- Ox.Button({
- id: 'close',
- title: Ox._('Close')
- }).bindEvent({
- click: function() {
- that.close();
- }
- }),
- ],
- keys: {enter: 'close', escape: 'close'},
- content: $content,
- title: "Share current view",
- });
- return that;
-}
diff --git a/static/mobile/css/reset.css b/static/mobile/css/reset.css
deleted file mode 100644
index b84ca0d8..00000000
--- a/static/mobile/css/reset.css
+++ /dev/null
@@ -1,46 +0,0 @@
-/* http://meyerweb.com/eric/tools/css/reset/
- v2.0 | 20110126
- License: none (public domain)
-*/
-
-html, body, div, span, applet, object, iframe,
-h1, h2, h3, h4, h5, h6, p, blockquote, pre,
-a, abbr, acronym, address, big, cite,
-del, dfn, em, img, ins, kbd, q, s, samp,
-small, strike, strong, sub, sup, tt, var,
-u, i, center,
-ol,
-fieldset, form, label, legend,
-table, caption, tbody, tfoot, thead, tr, th, td,
-article, aside, canvas, details, embed,
-figure, figcaption, footer, header, hgroup,
-menu, nav, output, ruby, section, summary,
-time, mark, audio, video {
- margin: 0;
- padding: 0;
- border: 0;
- font-size: 100%;
- font: inherit;
- vertical-align: baseline;
-}
-/* HTML5 display-role reset for older browsers */
-article, aside, details, figcaption, figure,
-footer, header, hgroup, menu, nav, section {
- display: block;
-}
-body {
- line-height: 1;
-
-}
-blockquote, q {
- quotes: none;
-}
-blockquote:before, blockquote:after,
-q:before, q:after {
- content: '';
- content: none;
-}
-table {
- border-collapse: collapse;
- border-spacing: 0;
-}
diff --git a/static/mobile/css/style.css b/static/mobile/css/style.css
deleted file mode 100644
index 811b250c..00000000
--- a/static/mobile/css/style.css
+++ /dev/null
@@ -1,171 +0,0 @@
-body {
- margin: 0;
- //background: rgb(240, 240, 240);
- //background: rgb(144, 144, 144);
- //color: rgb(0, 0, 0);
- background: rgb(16, 16, 16);
- color: rgb(240, 240, 240);
- font-family: "Noto Sans", "Lucida Grande", "Segoe UI", "DejaVu Sans", "Lucida Sans Unicode", Helvetica, Arial, sans-serif;
- line-height: normal;
-}
-
-a {
- color: rgb(128, 128, 255)
-}
-iframe {
- max-width: 100%;
-}
-
-.player {
- max-width: 100%;
-}
-video, .poster {
- border-bottom: 1px solid yellow;
-}
-.content {
- display: flex;
- flex-direction: column;
- min-height: 100vh;
- max-width: 1000px;
- margin: auto;
-}
-.title {
- padding-top: 16px;
- padding-bottom: 0;
- margin-bottom: 4px;
- font-size: 14pt;
- font-weight: bold;
- border-bottom: 1px solid pink;
- text-wrap: balance;
-}
-.byline {
- padding: 0;
- padding-bottom: 16px;
-}
-.player {
- text-align: center;
- padding-top: 0px;
- padding-bottom: 0px;
-}
-@media(max-width:768px) {
- .title,
- .byline {
- padding-left: 4px;
- padding-right: 4px;
- }
- .player {
- position: sticky;
- top: 0px;
- }
-}
-.player video {
- z-index: 0;
-}
-.value {
- padding: 4px;
- padding-top: 16px;
- padding-left: 0;
- padding-right: 0;
- flex: 1;
-}
-@media(max-width:768px) {
- .value {
- padding-left: 4px;
- padding-right: 4px;
- }
-}
-.more {
- padding-top: 16px;
- padding-bottom: 16px;
- text-align: center;
- font-size: 16pt;
-}
-.layer.active {
- padding-top: 8px;
-}
-.layer.active:first-child {
- padding-top: 0px;
-}
-.layer h3 {
- font-weight: bold;
- padding: 4px;
- padding-left: 0;
- margin: 0;
- //display: none;
-}
-.layer.active h3 {
- display: block;
-}
-
-.annotation {
- padding: 4px;
- border-bottom: 1px solid blueviolet;
- display: none;
-}
-.annotation.active {
- display: block;
-}
-.annotation.active.place,
-.annotation.active.string {
- display: inline-block;
- border: 1px solid blueviolet;
- margin-bottom: 4px;
-}
-@media(max-width:768px) {
- .annotation a img {
- width: 100%;
- }
-}
-
-.layer h3 {
- cursor: pointer;
-}
-.layer .icon svg {
- width: 12px;
- height: 12px;
-}
-.layer.collapsed .annotation.active {
- display: none;
-}
-.rotate {
- transform: rotate(90deg) translateY(-100%);
- transform-origin:bottom left;
-}
-
-.document.text {
- line-height: 1.5;
- letter-spacing: 0.1px;
- word-wrap: break-word;
- hyphens: auto;
-}
-.document.text p {
- padding-bottom: 1em;
-}
-.document.text img {
- max-width: 100vw;
- margin-left: -4px;
- margin-right: -4px;
-}
-figure {
- text-align: center;
-}
-figure img {
- max-width: 100vw;
- margin-left: -4px;
- margin-right: -4px;
-}
-@media(max-width:768px) {
-.document.text {
- padding-left: 4px;
- padding-right: 4px;
-}
-}
-
-ol li {
- margin-left: 1em;
-}
-
-.blocked svg {
- width: 64px;
- height: 64px;
-}
diff --git a/static/mobile/js/VideoElement.js b/static/mobile/js/VideoElement.js
deleted file mode 100644
index 8238d95d..00000000
--- a/static/mobile/js/VideoElement.js
+++ /dev/null
@@ -1,730 +0,0 @@
-'use strict';
-
-/*@
-VideoElement VideoElement Object
- options Options object
- autoplay autoplay
- items array of objects with src,in,out,duration
- loop loop playback
- playbackRate playback rate
- position start position
- self Shared private variable
- ([options[, self]]) -> VideoElement Object
- loadedmetadata loadedmetadata
- itemchange itemchange
- seeked seeked
- seeking seeking
- sizechange sizechange
- ended ended
-@*/
-
-(function() {
- var queue = [],
- queueSize = 100,
- restrictedElements = [],
- requiresUserGesture = mediaPlaybackRequiresUserGesture(),
- unblock = [];
-
-
-window.VideoElement = function(options) {
-
- var self = {},
- that = document.createElement("div");
-
- self.options = {
- autoplay: false,
- items: [],
- loop: false,
- muted: false,
- playbackRate: 1,
- position: 0,
- volume: 1
- }
- Object.assign(self.options, options);
- debug(self.options)
-
- that.style.position = "relative"
- that.style.width = "100%"
- that.style.height = "100%"
- that.style.maxHeight = "100vh"
- that.style.margin = 'auto'
- if (self.options.aspectratio) {
- that.style.aspectRatio = self.options.aspectratio
- } else {
- that.style.height = '128px'
- }
- that.triggerEvent = function(event, data) {
- if (event != 'timeupdate') {
- debug('Video', 'triggerEvent', event, data);
- }
- event = new Event(event)
- event.data = data
- that.dispatchEvent(event)
- }
-
-
- /*
- .update({
- items: function() {
- self.loadedMetadata = false;
- loadItems(function() {
- self.loadedMetadata = true;
- var update = true;
- if (self.currentItem >= self.numberOfItems) {
- self.currentItem = 0;
- }
- if (!self.numberOfItems) {
- self.video.src = '';
- that.triggerEvent('durationchange', {
- duration: that.duration()
- });
- } else {
- if (self.currentItemId != self.items[self.currentItem].id) {
- // check if current item is in new items
- self.items.some(function(item, i) {
- if (item.id == self.currentItemId) {
- self.currentItem = i;
- loadNextVideo();
- update = false;
- return true;
- }
- });
- if (update) {
- self.currentItem = 0;
- self.currentItemId = self.items[self.currentItem].id;
- }
- }
- if (!update) {
- that.triggerEvent('seeked');
- that.triggerEvent('durationchange', {
- duration: that.duration()
- });
- } else {
- setCurrentVideo(function() {
- that.triggerEvent('seeked');
- that.triggerEvent('durationchange', {
- duration: that.duration()
- });
- });
- }
- }
- });
- },
- playbackRate: function() {
- self.video.playbackRate = self.options.playbackRate;
- }
- })
- .css({width: '100%', height: '100%'});
- */
-
- debug('Video', 'VIDEO ELEMENT OPTIONS', self.options);
-
- self.currentItem = -1;
- self.currentTime = 0;
- self.currentVideo = 0;
- self.items = [];
- self.loadedMetadata = false;
- that.paused = self.paused = true;
- self.seeking = false;
- self.loading = true;
- self.buffering = true;
- self.videos = [getVideo(), getVideo()];
- self.video = self.videos[self.currentVideo];
- self.video.classList.add("active")
- self.volume = self.options.volume;
- self.muted = self.options.muted;
- self.brightness = document.createElement('div')
- self.brightness.style.top = '0'
- self.brightness.style.left = '0'
- self.brightness.style.width = '100%'
- self.brightness.style.height = '100%'
- self.brightness.style.background = 'rgb(0, 0, 0)'
- self.brightness.style.opacity = '0'
- self.brightness.style.position = "absolute"
- that.append(self.brightness)
-
- self.timeupdate = setInterval(function() {
- if (!self.paused
- && !self.loading
- && self.loadedMetadata
- && self.items[self.currentItem]
- && self.items[self.currentItem].out
- && self.video.currentTime >= self.items[self.currentItem].out) {
- setCurrentItem(self.currentItem + 1);
- }
- }, 30);
-
- // mobile browsers only allow playing media elements after user interaction
- if (restrictedElements.length > 0) {
- unblock.push(setSource)
- setTimeout(function() {
- that.triggerEvent('requiresusergesture');
- })
- } else {
- setSource();
- }
-
- function getCurrentTime() {
- var item = self.items[self.currentItem];
- return self.seeking || self.loading
- ? self.currentTime
- : item ? item.position + self.video.currentTime - item['in'] : 0;
- }
-
- function getset(key, value) {
- var ret;
- if (isUndefined(value)) {
- ret = self.video[key];
- } else {
- self.video[key] = value;
- ret = that;
- }
- return ret;
- }
-
- function getVideo() {
- var video = getVideoElement()
- video.style.display = "none"
- video.style.width = "100%"
- video.style.height = "100%"
- video.style.margin = "auto"
- video.style.background = '#000'
- if (self.options.aspectratio) {
- video.style.aspectRatio = self.options.aspectratio
- } else {
- video.style.height = '128px'
- }
- video.style.top = 0
- video.style.left = 0
- video.style.position = "absolute"
- video.preload = "metadata"
- video.addEventListener("ended", event => {
- if (self.video == video) {
- setCurrentItem(self.currentItem + 1);
- }
- })
- video.addEventListener("loadedmetadata", event => {
- //console.log("!!", video.src, "loaded", 'current?', video == self.video)
- })
- video.addEventListener("progress", event => {
- // stop buffering if buffered to end point
- var item = self.items[self.currentItem],
- nextItem = mod(self.currentItem + 1, self.numberOfItems),
- next = self.items[nextItem],
- nextVideo = self.videos[mod(self.currentVideo + 1, self.videos.length)];
- if (self.video == video && (video.preload != 'none' || self.buffering)) {
- if (clipCached(video, item)) {
- video.preload = 'none';
- self.buffering = false;
- if (nextItem != self.currentItem) {
- nextVideo.preload = 'auto';
- }
- } else {
- if (nextItem != self.currentItem && nextVideo.preload != 'none' && nextVideo.src) {
- nextVideo.preload = 'none';
- }
- }
- } else if (nextVideo == video && video.preload != 'none' && nextVideo.src) {
- if (clipCached(video, next)) {
- video.preload = 'none';
- }
- }
-
- function clipCached(video, item) {
- var cached = false
- for (var i=0; i= item.out) {
- cached = true
- }
- }
- return cached
- }
- })
- video.addEventListener("volumechange", event => {
- if (self.video == video) {
- that.triggerEvent('volumechange')
- }
- })
- video.addEventListener("play", event => {
- /*
- if (self.video == video) {
- that.triggerEvent('play')
- }
- */
- })
- video.addEventListener("pause", event => {
- /*
- if (self.video == video) {
- that.triggerEvent('pause')
- }
- */
- })
- video.addEventListener("timeupdate", event => {
- if (self.video == video) {
- /*
- var box = self.video.getBoundingClientRect()
- if (box.width && box.height) {
- that.style.width = box.width + 'px'
- that.style.height = box.height + 'px'
- }
- */
- that.triggerEvent('timeupdate', {
- currentTime: getCurrentTime()
- })
- }
- })
- video.addEventListener("seeking", event => {
- if (self.video == video) {
- that.triggerEvent('seeking')
- }
- })
- video.addEventListener("stop", event => {
- if (self.video == video) {
- //self.video.pause();
- that.triggerEvent('ended');
- }
- })
- that.append(video)
- return video
- }
-
- function getVideoElement() {
- var video;
- if (requiresUserGesture) {
- if (queue.length) {
- video = queue.pop();
- } else {
- video = document.createElement('video');
- restrictedElements.push(video);
- }
- } else {
- video = document.createElement('video');
- }
- video.playsinline = true
- video.setAttribute('playsinline', 'playsinline')
- video.setAttribute('webkit-playsinline', 'webkit-playsinline')
- video.WebKitPlaysInline = true
- return video
- };
-
- function getVolume() {
- var volume = 1;
- if (self.items[self.currentItem] && isNumber(self.items[self.currentItem].volume)) {
- volume = self.items[self.currentItem].volume;
- }
- return self.volume * volume;
- }
-
-
- function isReady(video, callback) {
- if (video.seeking && !self.paused && !self.seeking) {
- that.triggerEvent('seeking');
- debug('Video', 'isReady', 'seeking');
- video.addEventListener('seeked', function(event) {
- debug('Video', 'isReady', 'seeked');
- that.triggerEvent('seeked');
- callback(video);
- }, {once: true})
- } else if (video.readyState) {
- callback(video);
- } else {
- that.triggerEvent('seeking');
- video.addEventListener('loadedmetadata', function(event) {
- callback(video);
- }, {once: true});
- video.addEventListener('seeked', event => {
- that.triggerEvent('seeked');
- }, {once: true})
- }
- }
-
- function loadItems(callback) {
- debug('loadItems')
- var currentTime = 0,
- items = self.options.items.map(function(item) {
- return isObject(item) ? {...item} : {src: item};
- });
-
- self.items = items;
- self.numberOfItems = self.items.length;
- items.forEach(item => {
- item['in'] = item['in'] || 0;
- item.position = currentTime;
- if (item.out) {
- item.duration = item.out - item['in'];
- }
- if (item.duration) {
- if (!item.out) {
- item.out = item.duration;
- }
- currentTime += item.duration;
- item.id = getId(item);
- } else {
- getVideoInfo(item.src, function(info) {
- item.duration = info.duration;
- if (!item.out) {
- item.out = item.duration;
- }
- currentTime += item.duration;
- item.id = getId(item);
- });
- }
- })
- debug('loadItems done')
- callback && callback();
-
- function getId(item) {
- return item.id || item.src + '/' + item['in'] + '-' + item.out;
- }
- }
-
- function loadNextVideo() {
- if (self.numberOfItems <= 1) {
- return;
- }
- var item = self.items[self.currentItem],
- nextItem = mod(self.currentItem + 1, self.numberOfItems),
- next = self.items[nextItem],
- nextVideo = self.videos[mod(self.currentVideo + 1, self.videos.length)];
- nextVideo.addEventListener('loadedmetadata', function() {
- if (self.video != nextVideo) {
- nextVideo.currentTime = next['in'] || 0;
- }
- }, {once: true});
- nextVideo.src = next.src;
- nextVideo.preload = 'metadata';
- }
-
- function setCurrentItem(item) {
- debug('Video', 'sCI', item, self.numberOfItems);
- var interval;
- if (item >= self.numberOfItems || item < 0) {
- if (self.options.loop) {
- item = mod(item, self.numberOfItems);
- } else {
- self.seeking = false;
- self.ended = true;
- that.paused = self.paused = true;
- self.video && self.video.pause();
- that.triggerEvent('ended');
- return;
- }
- }
- self.video && self.video.pause();
- self.currentItem = item;
- self.currentItemId = self.items[self.currentItem].id;
- setCurrentVideo(function() {
- if (!self.loadedMetadata) {
- self.loadedMetadata = true;
- that.triggerEvent('loadedmetadata');
- }
- debug('Video', 'sCI', 'trigger itemchange',
- self.items[self.currentItem]['in'], self.video.currentTime, self.video.seeking);
- that.triggerEvent('sizechange');
- that.triggerEvent('itemchange', {
- item: self.currentItem
- });
- });
- }
-
- function setCurrentVideo(callback) {
- var css = {},
- muted = self.muted,
- item = self.items[self.currentItem],
- next;
- debug('Video', 'sCV', JSON.stringify(item));
-
- ['left', 'top', 'width', 'height'].forEach(function(key) {
- css[key] = self.videos[self.currentVideo].style[key];
- });
- self.currentTime = item.position;
- self.loading = true;
- if (self.video) {
- self.videos[self.currentVideo].style.display = "none"
- self.videos[self.currentVideo].classList.remove("active")
- self.video.pause();
- }
- self.currentVideo = mod(self.currentVideo + 1, self.videos.length);
- self.video = self.videos[self.currentVideo];
- self.video.classList.add("active")
- self.video.muted = true; // avoid sound glitch during load
- if (!self.video.attributes.src || self.video.attributes.src.value != item.src) {
- self.loadedMetadata && debug('Video', 'caching next item failed, reset src');
- self.video.src = item.src;
- }
- self.video.preload = 'metadata';
- self.video.volume = getVolume();
- self.video.playbackRate = self.options.playbackRate;
- Object.keys(css).forEach(key => {
- self.video.style[key] = css[key]
- })
- self.buffering = true;
- debug('Video', 'sCV', self.video.src, item['in'],
- self.video.currentTime, self.video.seeking);
- isReady(self.video, function(video) {
- var in_ = item['in'] || 0;
-
- function ready() {
- debug('Video', 'sCV', 'ready');
- self.seeking = false;
- self.loading = false;
- self.video.muted = muted;
- !self.paused && self.video.play();
- self.video.style.display = 'block'
- callback && callback();
- loadNextVideo();
- }
- if (video.currentTime == in_) {
- debug('Video', 'sCV', 'already at position', item.id, in_, video.currentTime);
- ready();
- } else {
- self.video.addEventListener("seeked", event => {
- debug('Video', 'sCV', 'seeked callback');
- ready();
- }, {once: true})
- if (!self.seeking) {
- debug('Video', 'sCV set in', video.src, in_, video.currentTime, video.seeking);
- self.seeking = true;
- video.currentTime = in_;
- if (self.paused) {
- var promise = self.video.play();
- if (promise !== undefined) {
- promise.then(function() {
- self.video.pause();
- self.video.muted = muted;
- }).catch(function() {
- self.video.pause();
- self.video.muted = muted;
- });
- } else {
- self.video.pause();
- self.video.muted = muted;
- }
- }
- }
- }
- });
- }
-
- function setCurrentItemTime(currentTime) {
- debug('Video', 'sCIT', currentTime, self.video.currentTime,
- 'delta', currentTime - self.video.currentTime);
- isReady(self.video, function(video) {
- if (self.video == video) {
- if(self.video.seeking) {
- self.video.addEventListener("seeked", event => {
- that.triggerEvent('seeked');
- self.seeking = false;
- }, {once: true})
- } else if (self.seeking) {
- that.triggerEvent('seeked');
- self.seeking = false;
- }
- video.currentTime = currentTime;
- }
- });
- }
-
- function setCurrentTime(time) {
- debug('Video', 'sCT', time);
- var currentTime, currentItem;
- self.items.forEach(function(item, i) {
- if (time >= item.position
- && time < item.position + item.duration) {
- currentItem = i;
- currentTime = time - item.position + item['in'];
- return false;
- }
- });
- if (self.items.length) {
- // Set to end of items if time > duration
- if (isUndefined(currentItem) && isUndefined(currentTime)) {
- currentItem = self.items.length - 1;
- currentTime = self.items[currentItem].duration + self.items[currentItem]['in'];
- }
- debug('Video', 'sCT', time, '=>', currentItem, currentTime);
- if (currentItem != self.currentItem) {
- setCurrentItem(currentItem);
- }
- self.seeking = true;
- self.currentTime = time;
- that.triggerEvent('seeking');
- setCurrentItemTime(currentTime);
- } else {
- self.currentTime = 0;
- }
- }
-
- function setSource() {
- self.loadedMetadata = false;
- loadItems(function() {
- setCurrentTime(self.options.position);
- self.options.autoplay && setTimeout(function() {
- that.play();
- });
- });
- }
-
-
- /*@
- brightness get/set brightness
- @*/
- that.brightness = function() {
- var ret;
- if (arguments.length == 0) {
- ret = 1 - parseFloat(self.brightness.style.opacity);
- } else {
- self.brightness.style.opacity = 1 - arguments[0]
- ret = that;
- }
- return ret;
- };
-
- /*@
- buffered buffered
- @*/
- that.buffered = function() {
- return self.video.buffered;
- };
-
- /*@
- currentTime get/set currentTime
- @*/
- that.currentTime = function() {
- var ret;
- if (arguments.length == 0) {
- ret = getCurrentTime();
- } else {
- self.ended = false;
- setCurrentTime(arguments[0]);
- ret = that;
- }
- return ret;
- };
-
- /*@
- duration duration
- @*/
- that.duration = function() {
- return self.items ? self.items.reduce((duration, item) => {
- return duration + item.duration;
- }, 0) : NaN;
- };
-
- /*@
- muted get/set muted
- @*/
- that.muted = function(value) {
- if (!isUndefined(value)) {
- self.muted = value;
- }
- return getset('muted', value);
- };
-
- /*@
- pause pause
- @*/
- that.pause = function() {
- that.paused = self.paused = true;
- self.video.pause();
- that.paused && that.triggerEvent('pause')
- };
-
- /*@
- play play
- @*/
- that.play = function() {
- if (self.ended) {
- that.currentTime(0);
- }
- isReady(self.video, function(video) {
- self.ended = false;
- that.paused = self.paused = false;
- self.seeking = false;
- video.play();
- that.triggerEvent('play')
- });
- };
-
- that.removeElement = function() {
- self.currentTime = getCurrentTime();
- self.loading = true;
- clearInterval(self.timeupdate);
- //Chrome does not properly release resources, reset manually
- //http://code.google.com/p/chromium/issues/detail?id=31014
- self.videos.forEach(function(video) {
- video.src = ''
- });
- return Ox.Element.prototype.removeElement.apply(that, arguments);
- };
-
- /*@
- videoHeight get videoHeight
- @*/
- that.videoHeight = function() {
- return self.video.videoHeight;
- };
-
- /*@
- videoWidth get videoWidth
- @*/
- that.videoWidth = function() {
- return self.video.videoWidth;
- };
-
- /*@
- volume get/set volume
- @*/
- that.volume = function(value) {
- if (isUndefined(value)) {
- value = self.volume
- } else {
- self.volume = value;
- self.video.volume = getVolume();
- }
- return value;
- };
-
- return that;
-
-};
-
-// mobile browsers only allow playing media elements after user interaction
-
- function mediaPlaybackRequiresUserGesture() {
- // test if play() is ignored when not called from an input event handler
- var video = document.createElement('video');
- video.muted = true
- video.play();
- return video.paused;
- }
-
-
- async function removeBehaviorsRestrictions() {
- debug('Video', 'remove restrictions on video', self.video, restrictedElements.length, queue.length);
- if (restrictedElements.length > 0) {
- var rElements = restrictedElements;
- restrictedElements = [];
- rElements.forEach(async function(video) {
- await video.load();
- });
- setTimeout(function() {
- var u = unblock;
- unblock = [];
- u.forEach(function(callback) { callback(); });
- }, 1000);
- }
- while (queue.length < queueSize) {
- var video = document.createElement('video');
- video.load();
- queue.push(video);
- }
- }
-
- if (requiresUserGesture) {
- window.addEventListener('keydown', removeBehaviorsRestrictions);
- window.addEventListener('mousedown', removeBehaviorsRestrictions);
- window.addEventListener('touchstart', removeBehaviorsRestrictions);
- }
-})();
diff --git a/static/mobile/js/VideoPlayer.js b/static/mobile/js/VideoPlayer.js
deleted file mode 100644
index 829fc02f..00000000
--- a/static/mobile/js/VideoPlayer.js
+++ /dev/null
@@ -1,400 +0,0 @@
-(function() {
-
-window.VideoPlayer = function(options) {
-
- var self = {}, that;
- self.options = {
- autoplay: false,
- controls: true,
- items: [],
- loop: false,
- muted: false,
- playbackRate: 1,
- position: 0,
- volume: 1
- }
- Object.assign(self.options, options);
- that = VideoElement(options);
-
- self.controls = document.createElement('div')
- self.controls.classList.add('mx-controls')
- //self.controls.style.display = "none"
- if (self.options.controls) {
- var ratio = `aspect-ratio: ${self.options.aspectratio};`
- if (!self.options.aspectratio) {
- ratio = 'height: 128px;'
- }
- self.controls.innerHTML = `
-
-
-
-
- ${icon.mute}
-
-
-
-
- ${isIOS || !self.options.aspectratio ? "" : icon.enterFullscreen}
-
-
- `
- var toggleVideo = event => {
- event.preventDefault()
- event.stopPropagation()
- if (that.paused) {
- that.play()
- } else {
- that.pause()
- }
- }
- async function toggleFullscreen(event) {
- if (isIOS) {
- return
- }
- event.preventDefault()
- event.stopPropagation()
- if (!document.fullscreenElement) {
- that.classList.add('fullscreen')
- if (that.webkitRequestFullscreen) {
- await that.webkitRequestFullscreen()
- } else {
- await that.requestFullscreen()
- }
- console.log('entered fullscreen')
- var failed = false
- if (!screen.orientation.type.startsWith("landscape")) {
- await screen.orientation.lock("landscape").catch(err => {
- console.log('no luck with lock', err)
- /*
- document.querySelector('.error').innerHTML = '' + err
- that.classList.remove('fullscreen')
- document.exitFullscreen();
- screen.orientation.unlock()
- failed = true
- */
- })
- }
- if (that.paused && !failed) {
- that.play()
- }
- } else {
- that.classList.remove('fullscreen')
- document.exitFullscreen();
- screen.orientation.unlock()
- }
- }
- var toggleSound = event => {
- event.preventDefault()
- event.stopPropagation()
- if (that.muted()) {
- that.muted(false)
- } else {
- that.muted(true)
- }
- }
- var showControls
- var toggleControls = event => {
- if (self.controls.style.opacity == '0') {
- event.preventDefault()
- event.stopPropagation()
- self.controls.style.opacity = '1'
- showControls = setTimeout(() => {
- self.controls.style.opacity = that.paused ? '1' : '0'
- showControls = null
- }, 3000)
- } else {
- self.controls.style.opacity = '0'
- }
- }
- self.controls.addEventListener("mousemove", event => {
- if (showControls) {
- clearTimeout(showControls)
- }
- self.controls.style.opacity = '1'
- showControls = setTimeout(() => {
- self.controls.style.opacity = that.paused ? '1' : '0'
- showControls = null
- }, 3000)
- })
- self.controls.addEventListener("mouseleave", event => {
- if (showControls) {
- clearTimeout(showControls)
- }
- self.controls.style.opacity = that.paused ? '1' : '0'
- showControls = null
- })
- self.controls.addEventListener("touchstart", toggleControls)
- self.controls.querySelector('.toggle').addEventListener("click", toggleVideo)
- self.controls.querySelector('.volume').addEventListener("click", toggleSound)
- self.controls.querySelector('.fullscreen-btn').addEventListener("click", toggleFullscreen)
- document.addEventListener('fullscreenchange', event => {
- if (!document.fullscreenElement) {
- screen.orientation.unlock()
- that.classList.remove('fullscreen')
- that.querySelector('.fullscreen-btn').innerHTML = icon.enterFullscreen
- } else {
- self.controls.querySelector('.fullscreen-btn').innerHTML = icon.exitFullscreen
- }
- })
- that.append(self.controls)
- }
-
- function getVideoWidth() {
- if (document.fullscreenElement) {
- return ''
- }
- var av = that.querySelector('video.active')
- return av ? av.getBoundingClientRect().width + 'px' : '100%'
- }
-
- var playOnLoad = false
- var unblock = document.createElement("div")
-
- that.addEventListener("requiresusergesture", event => {
- unblock.style.position = "absolute"
- unblock.style.width = '100%'
- unblock.style.height = '100%'
- unblock.style.backgroundImage = `url(${self.options.poster})`
- unblock.style.zIndex = '1000'
- unblock.style.backgroundPosition = "top left"
- unblock.style.backgroundRepeat = "no-repeat"
- unblock.style.backgroundSize = "cover"
- unblock.style.display = 'flex'
- unblock.classList.add('mx-controls')
- unblock.classList.add('poster')
- unblock.innerHTML = `
-
-
- `
- self.controls.style.opacity = '0'
- unblock.addEventListener("click", event => {
- event.preventDefault()
- event.stopPropagation()
- playOnLoad = true
- unblock.querySelector('.toggle').innerHTML = `
- ${icon.loading}
- `
- }, {once: true})
- that.append(unblock)
- })
- var loading = true
- that.brightness(0)
- that.addEventListener("loadedmetadata", event => {
- //
- })
- that.addEventListener("seeked", event => {
- if (loading) {
- that.brightness(1)
- loading = false
- }
- if (playOnLoad) {
- playOnLoad = false
- var toggle = self.controls.querySelector('.toggle')
- toggle.title = 'Pause'
- toggle.querySelector('div').innerHTML = icon.pause
- self.controls.style.opacity = '0'
- unblock.remove()
- that.play()
- }
- })
-
- var time = that.querySelector('.controls .time div'),
- progress = that.querySelector('.controls .position .progress')
- that.querySelector('.controls .position').addEventListener("click", event => {
- var bar = event.target
- while (bar && !bar.classList.contains('bar')) {
- bar = bar.parentElement
- }
- if (bar && bar.classList.contains('bar')) {
- event.preventDefault()
- event.stopPropagation()
- var rect = bar.getBoundingClientRect()
- var x = event.clientX - rect.x
- var percent = x / rect.width
- var position = percent * self.options.duration
- if (self.options.position) {
- position += self.options.position
- }
- progress.style.width = (100 * percent) + '%'
- that.currentTime(position)
- }
- })
- that.addEventListener("timeupdate", event => {
- var currentTime = that.currentTime(),
- duration = self.options.duration
- if (self.options.position) {
- currentTime -= self.options.position
- }
- progress.style.width = (100 * currentTime / duration) + '%'
- duration = formatDuration(duration)
- currentTime = formatDuration(currentTime)
- while (duration && duration.startsWith('00:')) {
- duration = duration.slice(3)
- }
- currentTime = currentTime.slice(currentTime.length - duration.length)
- time.innerText = `${currentTime} / ${duration}`
-
- })
-
- that.addEventListener("play", event => {
- var toggle = self.controls.querySelector('.toggle')
- toggle.title = 'Pause'
- toggle.querySelector('div').innerHTML = icon.pause
- self.controls.style.opacity = '0'
- })
- that.addEventListener("pause", event => {
- var toggle = self.controls.querySelector('.toggle')
- toggle.title = 'Play'
- toggle.querySelector('div').innerHTML = icon.play
- self.controls.style.opacity = '1'
- })
- that.addEventListener("ended", event => {
- var toggle = self.controls.querySelector('.toggle')
- toggle.title = 'Play'
- toggle.querySelector('div').innerHTML = icon.play
- self.controls.style.opacity = '1'
- })
- that.addEventListener("seeking", event => {
- //console.log("seeking")
-
- })
- that.addEventListener("seeked", event => {
- //console.log("seeked")
- })
- that.addEventListener("volumechange", event => {
- var volume = self.controls.querySelector('.volume')
- if (that.muted()) {
- volume.innerHTML = icon.unmute
- volume.title = "Unmute"
- } else {
- volume.innerHTML = icon.mute
- volume.title = "Mute"
- }
- })
- window.addEventListener('resize', event => {
- //
- })
- return that
-};
-
-})();
diff --git a/static/mobile/js/api.js b/static/mobile/js/api.js
deleted file mode 100644
index 5e989597..00000000
--- a/static/mobile/js/api.js
+++ /dev/null
@@ -1,25 +0,0 @@
-var pandora = {
- format: getFormat(),
- hostname: document.location.hostname || 'pad.ma'
-}
-
-var pandoraURL = document.location.hostname ? "" : `https://${pandora.hostname}`
-var cache = cache || {}
-
-async function pandoraAPI(action, data) {
- var url = pandoraURL + '/api/'
- var key = JSON.stringify([action, data])
- if (!cache[key]) {
- var response = await fetch(url, {
- method: 'POST',
- headers: {'Content-Type': 'application/json'},
- body: JSON.stringify({
- action: action,
- data: data
- })
- })
- cache[key] = await response.json()
- }
- return cache[key]
-}
-
diff --git a/static/mobile/js/documents.js b/static/mobile/js/documents.js
deleted file mode 100644
index 2d58b0ff..00000000
--- a/static/mobile/js/documents.js
+++ /dev/null
@@ -1,112 +0,0 @@
-
-async function loadDocument(id, args) {
- var data = window.data = {}
- var parts = id.split('/')
- data.id = parts.shift()
- data.site = pandora.hostname
-
- if (parts.length == 2) {
- data.page = parts.shift()
- }
-
- if (parts.length == 1) {
- var rect = parts[0].split(',')
- if (rect.length == 1) {
- data.page = parts[0]
- } else {
- data.crop = rect
- }
- } else if (parts.length == 2) {
-
- }
-
- var response = await pandoraAPI('getDocument', {
- id: data.id,
- keys: [
- "id",
- "title",
- "extension",
- "text",
- ]
- })
- if (response.status.code != 200) {
- return {
- site: data.site,
- error: response.status
- }
- }
- data.document = response['data']
- data.title = data.document.name
- data.link = `${pandora.proto}://${data.site}/documents/${data.document.id}`
- return data
-}
-
-async function renderDocument(data) {
- if (data.error) {
- return renderError(data)
- }
- div = document.createElement('div')
- div.className = "content"
- if (!data.document) {
- div.innerHTML = ``
- } else if (data.document.extension == "html") {
- div.innerHTML = `
- ${data.document.title}
-
- ${data.document.text}
-
-
- `
- div.querySelectorAll('.text a').forEach(a => {
- a.addEventListener("click", clickLink)
-
- })
- } else if (data.document.extension == "pdf" && data.page && data.crop) {
- var img = `${pandora.proto}://${data.site}/documents/${data.document.id}/1024p${data.page},${data.crop.join(',')}.jpg`
- data.link = getLink(`documents/${data.document.id}/${data.page}`)
- div.innerHTML = `
- ${data.document.title}
-
-

-
-
- `
- } else if (data.document.extension == "pdf") {
- var page = data.page || 1,
- file = encodeURIComponent(`/documents/${data.document.id}/${safeDocumentName(data.document.title)}.pdf`)
- div.innerHTML = `
- ${data.document.title}
-
-
-
-
- `
- } else if (data.document.extension == "jpg" || data.document.extension == "png") {
- var img = `${pandora.proto}://${data.site}/documents/${data.document.id}/${safeDocumentName(data.document.title)}.${data.document.extension}`
- var open_text = `Open on ${data.site}`
- if (data.crop) {
- img = `${pandora.proto}://${data.site}/documents/${data.document.id}/1024p${data.crop.join(',')}.jpg`
- data.link = getLink(`documents/${data.document.id}`)
- open_text = `Open image`
- }
- div.innerHTML = `
- ${data.document.title}
-
-

-
-
- `
-
- } else {
- div.innerHTML = `unsupported document type`
- }
- document.querySelector(".content").replaceWith(div)
-}
diff --git a/static/mobile/js/edits.js b/static/mobile/js/edits.js
deleted file mode 100644
index f23766ef..00000000
--- a/static/mobile/js/edits.js
+++ /dev/null
@@ -1,230 +0,0 @@
-
-const getSortValue = function(value) {
- var sortValue = value;
- function trim(value) {
- return value.replace(/^\W+(?=\w)/, '');
- }
- if (
- isEmpty(value)
- || isNull(value)
- || isUndefined(value)
- ) {
- sortValue = null;
- } else if (isString(value)) {
- // make lowercase and remove leading non-word characters
- sortValue = trim(value.toLowerCase());
- // move leading articles to the end
- // and remove leading non-word characters
- ['a', 'an', 'the'].forEach(function(article) {
- if (new RegExp('^' + article + ' ').test(sortValue)) {
- sortValue = trim(sortValue.slice(article.length + 1))
- + ', ' + sortValue.slice(0, article.length);
- return false; // break
- }
- });
- // remove thousand separators and pad numbers
- sortValue = sortValue.replace(/(\d),(?=(\d{3}))/g, '$1')
- .replace(/\d+/g, function(match) {
- return match.padStart(64, '0')
- });
- }
- return sortValue;
-};
-
-const sortByKey = function(array, by) {
- return array.sort(function(a, b) {
- var aValue, bValue, index = 0, key, ret = 0;
- while (ret == 0 && index < by.length) {
- key = by[index].key;
- aValue = getSortValue(a[key])
- bValue = getSortValue(b[key])
- if ((aValue === null) != (bValue === null)) {
- ret = aValue === null ? 1 : -1;
- } else if (aValue < bValue) {
- ret = by[index].operator == '+' ? -1 : 1;
- } else if (aValue > bValue) {
- ret = by[index].operator == '+' ? 1 : -1;
- } else {
- index++;
- }
- }
- return ret;
- });
-};
-
-async function sortClips(edit, sort) {
- var key = sort.key, index;
- if (key == 'position') {
- key = 'in';
- }
- if ([
- 'id', 'index', 'in', 'out', 'duration',
- 'title', 'director', 'year', 'videoRatio'
- ].indexOf(key) > -1) {
- sortBy(sort);
- index = 0;
- edit.clips.forEach(function(clip) {
- clip.sort = index++;
- if (sort.operator == '-') {
- clip.sort = -clip.sort;
- }
- });
- } else {
- var response = await pandoraAPI('sortClips', {
- edit: edit.id,
- sort: [sort]
- })
- edit.clips.forEach(function(clip) {
- clip.sort = response.data.clips.indexOf(clip.id);
- if (sort.operator == '-') {
- clip.sort = -clip.sort;
- }
- });
- sortBy({
- key: 'sort',
- operator: '+'
- });
- }
- function sortBy(key) {
- edit.clips = sortByKey(edit.clips, [key]);
- }
-}
-
-async function loadEdit(id, args) {
- var data = window.data = {}
- data.id = id
- data.site = pandora.hostname
-
- var response = await pandoraAPI('getEdit', {
- id: data.id,
- keys: [
- ]
- })
- if (response.status.code != 200) {
- return {
- site: data.site,
- error: response.status
- }
- }
- data.edit = response['data']
- if (data.edit.status !== 'public') {
- return {
- site: data.site,
- error: {
- code: 403,
- text: 'permission denied'
- }
- }
- }
- data.layers = {}
- data.videos = []
-
- if (args.sort) {
- await sortClips(data.edit, args.sort)
- }
-
- data.edit.duration = 0;
- data.edit.clips.forEach(function(clip) {
- clip.position = data.edit.duration;
- data.edit.duration += clip.duration;
- });
-
- data.edit.clips.forEach(clip => {
- var start = clip['in'] || 0, end = clip.out, position = 0;
- clip.durations.forEach((duration, idx) => {
- if (!duration) {
- return
- }
- if (position + duration <= start || position > end) {
- // pass
- } else {
- var video = {}
- var oshash = clip.streams[idx]
- video.src = getVideoURL(clip.item, 480, idx+1, '', oshash)
- /*
- if (clip['in'] && clip.out) {
- video.src += `#t=${clip['in']},${clip.out}`
- }
- */
- if (isNumber(clip.volume)) {
- video.volume = clip.volume;
- }
- if (
- position <= start
- && position + duration > start
- ) {
- video['in'] = start - position;
- }
- if (position + duration >= end) {
- video.out = end - position;
- }
- if (video['in'] && video.out) {
- video.duration = video.out - video['in']
- } else if (video.out) {
- video.duration = video.out;
- } else if (!isUndefined(video['in'])) {
- video.duration = duration - video['in'];
- video.out = duration;
- } else {
- video.duration = duration;
- video['in'] = 0;
- video.out = video.duration;
- }
- data.videos.push(video)
- }
- position += duration
- })
- Object.keys(clip.layers).forEach(layer => {
- data.layers[layer] = data.layers[layer] || []
- clip.layers[layer].forEach(annotation => {
- if (args.users && !args.users.includes(annotation.user)) {
- return
- }
- if (args.layers && !args.layers.includes(layer)) {
- return
- }
- var a = {...annotation}
- a['id'] = clip['id'] + '/' + a['id'];
- a['in'] = Math.max(
- clip['position'],
- a['in'] - clip['in'] + clip['position']
- );
- a.out = Math.min(
- clip['position'] + clip['duration'],
- a.out - clip['in'] + clip['position']
- );
- data.layers[layer].push(a)
- })
- })
- })
- var value = []
- pandora.layerKeys.forEach(layer => {
- if (!data.layers[layer]) {
- return
- }
- var html = []
- var layerData = getObjectById(pandora.site.layers, layer)
- html.push(`
- ${icon.down}
- ${layerData.title}
-
`)
- data.layers[layer].forEach(annotation => {
- html.push(`
-
- ${annotation.value}
-
- `)
- })
- value.push('' + html.join('\n') + '
')
- })
- data.value = value.join('\n')
-
- data.title = data.edit.name
- data.byline = data.edit.description
- data.link = `${pandora.proto}://${data.site}/edits/${data.edit.id}`
- data.poster = data.videos[0].src.split('/48')[0] + `/480p${data.videos[0].in}.jpg`
- data.aspectratio = data.edit.clips[0].videoRatio
- data.duration = data.edit.duration
- return data
-
-}
diff --git a/static/mobile/js/icons.js b/static/mobile/js/icons.js
deleted file mode 100644
index 295a12fe..00000000
--- a/static/mobile/js/icons.js
+++ /dev/null
@@ -1,182 +0,0 @@
-var icon = {}
-icon.enterFullscreen = `
-
-`
-icon.exitFullscreen = `
-
-`
-
-icon.mute = `
-
-
-`
-
-icon.unmute = `
-
-
-`
-
-icon.play = `
-
-`
-icon.pause = `
-
-
-`
-icon.loading = `
-
-`
-
-icon.right = `
-
-`
-icon.left = `
-
-`
-icon.down = `
-
-`
diff --git a/static/mobile/js/item.js b/static/mobile/js/item.js
deleted file mode 100644
index 61463aa5..00000000
--- a/static/mobile/js/item.js
+++ /dev/null
@@ -1,133 +0,0 @@
-
-async function loadData(id, args) {
- var data = window.data = {}
- data.id = id
- data.site = pandora.hostname
-
- var response = await pandoraAPI('get', {
- id: data.id.split('/')[0],
- keys: [
- "id",
- "title",
- "director",
- "summary",
- "streams",
- "duration",
- "durations",
- "layers",
- "rightslevel",
- "videoRatio"
- ]
- })
-
- if (response.status.code != 200) {
- return {
- site: data.site,
- error: response.status
- }
- }
- data.item = response['data']
- if (data.item.rightslevel > pandora.site.capabilities.canPlayClips['guest']) {
- return {
- site: data.site,
- error: {
- code: 403,
- text: 'permission denied'
- }
- }
- }
- if (id.split('/').length == 1 || id.split('/')[1] == 'info') {
- data.view = 'info'
- data.title = data.item.title
- data.byline = data.item.director ? data.item.director.join(', ') : ''
- data.link = `${pandora.proto}://${data.site}/${data.item.id}/info`
- let poster = pandora.site.user.ui.icons == 'posters' ? 'poster' : 'icon'
- data.icon = `${pandora.proto}://${data.site}/${data.item.id}/${poster}.jpg`
- return data
- }
-
- if (id.includes('-') || id.includes(',')) {
- var inout = id.split('/')[1].split(id.includes('-') ? '-' : ',').map(parseDuration)
- data.out = inout.pop()
- data['in'] = inout.pop()
- } else if (args.full) {
- data.out = data.item.duration
- data['in'] = 0
- } else {
- var annotation = await pandoraAPI('getAnnotation', {
- id: data.id,
- })
- if (annotation.status.code != 200) {
- return {
- site: data.site,
- error: annotation.status
- }
- }
- data.annotation = annotation['data']
- data['in'] = data.annotation['in']
- data.out = data.annotation['out']
- }
-
- data.layers = {}
-
- pandora.layerKeys.forEach(layer => {
- data.item.layers[layer].forEach(annot => {
- if (data.annotation) {
- if (annot.id == data.annotation.id) {
- data.layers[layer] = data.layers[layer] || []
- data["layers"][layer].push(annot)
- }
- } else if (annot['out'] > data['in'] && annot['in'] < data['out']) {
- if (args.users && !args.users.includes(annot.user)) {
- return
- }
- if (args.layers && !args.layers.includes(layer)) {
- return
- }
- data.layers[layer] = data.layers[layer] || []
- //annot['in'] = Math.max([annot['in'], data['in']])
- //annot['out'] = Math.min([annot['out'], data['out']])
- data["layers"][layer].push(annot)
- }
- })
- })
- data.videos = []
- data.item.durations.forEach((duration, idx) => {
- var oshash = data.item.streams[idx]
- var url = getVideoURL(data.item.id, 480, idx+1, '', oshash)
- data.videos.push({
- src: url,
- duration: duration
- })
- })
- var value = []
- Object.keys(data.layers).forEach(layer => {
- var html = []
- var layerData = getObjectById(pandora.site.layers, layer)
- html.push(`
- ${icon.down}
- ${layerData.title}
-
`)
- data.layers[layer].forEach(annotation => {
- html.push(`
-
- ${annotation.value}
-
- `)
- })
- value.push('' + html.join('\n') + '
')
- })
- data.value = value.join('\n')
-
- data.title = data.item.title
- data.byline = data.item.director ? data.item.director.join(', ') : ''
- data.link = `${pandora.proto}://${data.site}/${data.item.id}/${data["in"]},${data.out}`
- data.poster = `${pandora.proto}://${data.site}/${data.item.id}/480p${data["in"]}.jpg`
- data.aspectratio = data.item.videoRatio
- if (data['in'] == data['out']) {
- data['out'] += 0.04
- }
- data.duration = data.out - data['in']
- return data
-}
-
diff --git a/static/mobile/js/main.js b/static/mobile/js/main.js
deleted file mode 100644
index c69a9f79..00000000
--- a/static/mobile/js/main.js
+++ /dev/null
@@ -1,129 +0,0 @@
-
-
-function parseURL() {
- var fragment = document.location.hash.slice(1)
- if (!fragment && document.location.pathname.startsWith('/m/')) {
- var prefix = document.location.protocol + '//' + document.location.hostname + '/m/'
- fragment = document.location.href.slice(prefix.length)
- }
- var args = fragment.split('?')
- var id = args.shift()
- if (args) {
- args = args.join('?').split('&').map(arg => {
- var kv = arg.split('=')
- k = kv.shift()
- v = kv.join('=')
- if (['users', 'layers'].includes(k)) {
- v = v.split(',')
- }
- return [k, v]
- }).filter(kv => {
- return kv[0].length
- })
- if (args) {
- args = Object.fromEntries(args);
- } else {
- args = {}
- }
- } else {
- args = {}
- }
- var type = "item"
- if (id.startsWith('document')) {
- id = id.split('/')
- id.shift()
- id = id.join('/')
- type = "document"
- } else if (id.startsWith('edits/')) {
- var parts = id.split('/')
- parts.shift()
- id = parts.shift().replace(/_/g, ' ')
- type = "edit"
- if (parts.length >= 2) {
- args.sort = parts[1]
- if (args.sort[0] == '-') {
- args.sort = {
- key: args.sort.slice(1),
- operator: '-'
- }
- } else if (args.sort[0] == '+') {
- args.sort = {
- key: args.sort.slice(1),
- operator: '+'
- }
- } else {
- args.sort = {
- key: args.sort,
- operator: '+'
- }
- }
- }
- args.parts = parts
- } else {
- if (id.endsWith('/player') || id.endsWith('/editor')) {
- args.full = true
- }
- id = id.replace('/editor/', '/').replace('/player/', '/')
- type = "item"
- }
- return [type, id, args]
-}
-
-function render() {
- var type, id, args;
- [type, id, args] = parseURL()
- document.querySelector(".content").innerHTML = loadingScreen
- if (type == "document") {
- loadDocument(id, args).then(renderDocument)
- } else if (type == "edit") {
- loadEdit(id, args).then(renderItem)
- } else {
- loadData(id, args).then(renderItem)
- }
-
-}
-var loadingScreen = `
-
- ${icon.loading}
-`
-
-document.querySelector(".content").innerHTML = loadingScreen
-pandoraAPI("init").then(response => {
- pandora = {
- ...pandora,
- ...response.data
- }
- pandora.proto = pandora.site.site.https ? 'https' : 'http'
- if (pandora.site.site.videoprefix.startsWith('//')) {
- pandora.site.site.videoprefix = pandora.proto + ':' + pandora.site.site.videoprefix
- }
- var layerKeys = []
- var subtitleLayer = pandora.site.layers.filter(layer => {return layer.isSubtitles})[0]
- if (subtitleLayer) {
- layerKeys.push(subtitleLayer.id)
- }
- pandora.site.layers.map(layer => {
- return layer.id
- }).filter(layer => {
- return !subtitleLayer || layer != subtitleLayer.id
- }).forEach(layer => {
- layerKeys.push(layer)
- })
- pandora.layerKeys = layerKeys
- id = document.location.hash.slice(1)
- window.addEventListener("hashchange", event => {
- render()
- })
- window.addEventListener("popstate", event => {
- console.log("popsatte")
- render()
- })
- window.addEventListener('resize', event => {
- })
- render()
-})
diff --git a/static/mobile/js/render.js b/static/mobile/js/render.js
deleted file mode 100644
index a7519342..00000000
--- a/static/mobile/js/render.js
+++ /dev/null
@@ -1,120 +0,0 @@
-
-function renderItemInfo(data) {
- div = document.createElement('div')
- div.className = "content"
- div.innerHTML = `
- ${data.title}
- ${data.byline}
-
-
-
-
- `
- document.querySelector(".content").replaceWith(div)
-}
-
-function renderItem(data) {
- if (data.error) {
- return renderError(data)
- }
- if (data.view == "info") {
- return renderItemInfo(data)
- }
- div = document.createElement('div')
- div.className = "content"
- div.innerHTML = `
- ${data.title}
- ${data.byline}
-
- ${data.value}
-
- `
- var comments = `
-
- `
-
- div.querySelectorAll('.layer a').forEach(a => {
- a.addEventListener("click", clickLink)
- })
-
- div.querySelectorAll('.layer').forEach(layer => {
- layer.querySelector('h3').addEventListener("click", event => {
- var img = layer.querySelector('h3 .icon')
- if (layer.classList.contains("collapsed")) {
- layer.classList.remove("collapsed")
- img.innerHTML = icon.down
- } else {
- layer.classList.add("collapsed")
- img.innerHTML = icon.right
- }
- })
- })
-
- var video = window.video = VideoPlayer({
- items: data.videos,
- poster: data.poster,
- position: data["in"] || 0,
- duration: data.duration,
- aspectratio: data.aspectratio
- })
- div.querySelector('.video').replaceWith(video)
- video.classList.add('video')
-
- video.addEventListener("loadedmetadata", event => {
- //
- })
- video.addEventListener("timeupdate", event => {
- var currentTime = video.currentTime()
- if (currentTime >= data['out']) {
- if (!video.paused) {
- video.pause()
- }
- video.currentTime(data['in'])
- }
- div.querySelectorAll('.annotation').forEach(annot => {
- var now = currentTime
- var start = parseFloat(annot.dataset.in)
- var end = parseFloat(annot.dataset.out)
- if (now >= start && now <= end) {
- annot.classList.add("active")
- annot.parentElement.classList.add('active')
- } else {
- annot.classList.remove("active")
- if (!annot.parentElement.querySelector('.active')) {
- annot.parentElement.classList.remove('active')
- }
- }
- })
-
- })
- document.querySelector(".content").replaceWith(div)
-}
-
-function renderError(data) {
- var link = '/' + document.location.hash.slice(1)
- div = document.createElement('div')
- div.className = "content"
- div.innerHTML = `
-
-
- `
- document.querySelector(".content").replaceWith(div)
-}
diff --git a/static/mobile/js/utils.js b/static/mobile/js/utils.js
deleted file mode 100644
index d77024f1..00000000
--- a/static/mobile/js/utils.js
+++ /dev/null
@@ -1,160 +0,0 @@
-
-const parseDuration = function(string) {
- return string.split(':').reverse().slice(0, 4).reduce(function(p, c, i) {
- return p + (parseFloat(c) || 0) * (i == 3 ? 86400 : Math.pow(60, i));
- }, 0);
-};
-
-const formatDuration = function(seconds) {
- var parts = [
- parseInt(seconds / 86400),
- parseInt(seconds % 86400 / 3600),
- parseInt(seconds % 3600 / 60),
- s = parseInt(seconds % 60)
- ]
- return parts.map(p => { return p.toString().padStart(2, '0')}).join(':')
-}
-
-const typeOf = function(value) {
- return Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
-};
-const isUndefined = function(value) {
- return typeOf(value) == 'undefined';
-}
-const isNumber = function(value) {
- return typeOf(value) == 'number';
-};
-const isObject = function(value) {
- return typeOf(value) == 'object';
-};
-const isNull = function(value) {
- return typeOf(value) == 'null';
-};
-const isString = function(value) {
- return typeOf(value) == 'string';
-};
-const isEmpty = function(value) {
- var type = typeOf(value)
- if (['arguments', 'array', 'nodelist', 'string'].includes(value)) {
- return value.length == 0
- }
- if (['object', 'storage'].includes(type)) {
- return Object.keys(value).length;
- }
- return false
-};
-const mod = function(number, by) {
- return (number % by + by) % by;
-};
-
-const getObjectById = function(array, id) {
- return array.filter(obj => { return obj.id == id})[0]
-}
-
-const debug = function() {
- if (localStorage.debug) {
- console.log.apply(null, arguments)
- }
-};
-
-const canPlayMP4 = function() {
- var video = document.createElement('video');
- if (video.canPlayType && video.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace('no', '')) {
- return true
- }
- return false
-};
-
-const canPlayWebm = function() {
- var video = document.createElement('video');
- if (video.canPlayType && video.canPlayType('video/webm; codecs="vp8, vorbis"').replace('no', '')) {
- return true
- }
- return false
-};
-
-const getFormat = function() {
- //var format = canPlayWebm() ? "webm" : "mp4"
- var format = canPlayMP4() ? "mp4" : "webm"
- return format
-}
-
-const safeDocumentName = function(name) {
- ['\\?', '#', '%', '/'].forEach(function(c) {
- var r = new RegExp(c, 'g')
- name = name.replace(r, '_');
- })
- return name;
-};
-
-const getVideoInfo = function() {
- console.log("FIXME implement getvideoInfo")
-}
-
-const isIOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
-
-
-const getLink = function(fragment) {
- if (document.location.hash.length > 2) {
- return '#' + fragment
- } else {
- return '/m/' + fragment
- }
-}
-
-const clickLink = function(event) {
- var a = event.target
- while (a && a.tagName != 'A') {
- a = a.parentElement
- }
- if (!a) {
- return
- }
- var href = a.attributes.href.value
- var prefix = document.location.protocol + '//' + document.location.hostname
- if (href.startsWith(prefix)) {
- href = href.slice(prefix.length)
- }
- if (href.startsWith('/')) {
- event.preventDefault()
- event.stopPropagation()
- var link = href.split('#embed')[0]
- if (document.location.hash.length > 2) {
- if (link.startsWith('/m')) {
- link = link.slice(2)
- }
- document.location.hash = '#' + link.slice(1)
- } else {
- if (!link.startsWith('/m')) {
- link = '/m' + link
- }
- history.pushState({}, '', link);
- render()
- }
- }
-}
-
-const getUid = (function() {
- var uid = 0;
- return function() {
- return ++uid;
- };
-}());
-
-
-const getVideoURLName = function(id, resolution, part, track, streamId) {
- return id + '/' + resolution + 'p' + part + (track ? '.' + track : '')
- + '.' + pandora.format + (streamId ? '?' + streamId : '');
-};
-
-const getVideoURL = function(id, resolution, part, track, streamId) {
- var uid = getUid(),
- prefix = pandora.site.site.videoprefix
- .replace('{id}', id)
- .replace('{part}', part)
- .replace('{resolution}', resolution)
- .replace('{uid}', uid)
- .replace('{uid42}', uid % 42);
- return prefix + '/' + getVideoURLName(id, resolution, part, track, streamId);
-};
-
diff --git a/update.py b/update.py
index 5cf0dfca..2cc118f6 100755
--- a/update.py
+++ b/update.py
@@ -303,8 +303,6 @@ if __name__ == "__main__":
run('./bin/pip', 'install', 'yt-dlp>=2022.3.8.2')
if old < 6465:
run('./bin/pip', 'install', '-r', 'requirements.txt')
- if old < 6507:
- run('./bin/pip', 'install', '-r', 'requirements.txt')
else:
if len(sys.argv) == 1:
branch = get_branch()
-