nodes
This commit is contained in:
parent
1436b14003
commit
75a14fed1e
18 changed files with 251 additions and 121 deletions
|
@ -110,7 +110,8 @@
|
||||||
"title": "Extension",
|
"title": "Extension",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"columnWidth": 80,
|
"columnWidth": 80,
|
||||||
"sort": true
|
"sort": true,
|
||||||
|
"find": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "size",
|
"id": "size",
|
||||||
|
@ -319,6 +320,7 @@
|
||||||
"username": ""
|
"username": ""
|
||||||
},
|
},
|
||||||
"ui": {
|
"ui": {
|
||||||
|
"coverSize": 256,
|
||||||
"fileInfo": "extension",
|
"fileInfo": "extension",
|
||||||
"filters": [
|
"filters": [
|
||||||
{"id": "author", "sort": [{"key": "items", "operator": "-"}]},
|
{"id": "author", "sort": [{"key": "items", "operator": "-"}]},
|
||||||
|
|
4
ctl
4
ctl
|
@ -90,8 +90,8 @@ if [ "$1" == "update" ]; then
|
||||||
cd $BASE/$NAME
|
cd $BASE/$NAME
|
||||||
git pull
|
git pull
|
||||||
find . -name '*.pyc' -exec rm "{}" \;
|
find . -name '*.pyc' -exec rm "{}" \;
|
||||||
$0 setup
|
python2 oml setup
|
||||||
$0 update_static > /dev/null
|
python2 oml update_static > /dev/null
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
@ -151,7 +151,8 @@ class Changelog(db.Model):
|
||||||
if not i:
|
if not i:
|
||||||
i = Item.get_or_create(itemid, info)
|
i = Item.get_or_create(itemid, info)
|
||||||
i.modified = datetime.fromtimestamp(float(timestamp))
|
i.modified = datetime.fromtimestamp(float(timestamp))
|
||||||
i.users.append(user)
|
if user not in i.users:
|
||||||
|
i.users.append(user)
|
||||||
i.update()
|
i.update()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,6 @@ def api_acceptPeering(app, user_id, username, message):
|
||||||
user.info['username'] = username
|
user.info['username'] = username
|
||||||
user.info['message'] = message
|
user.info['message'] = message
|
||||||
user.update_peering(True, username)
|
user.update_peering(True, username)
|
||||||
trigger_event('peering.accept', user.json())
|
|
||||||
state.nodes.queue('add', user.id)
|
state.nodes.queue('add', user.id)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
71
oml/nodes.py
71
oml/nodes.py
|
@ -11,6 +11,7 @@ import gzip
|
||||||
import urllib2
|
import urllib2
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
import ox
|
import ox
|
||||||
import ed25519
|
import ed25519
|
||||||
|
@ -30,7 +31,8 @@ logger = logging.getLogger('oml.nodes')
|
||||||
|
|
||||||
ENCODING='base64'
|
ENCODING='base64'
|
||||||
|
|
||||||
class Node(object):
|
class Node(Thread):
|
||||||
|
_running = True
|
||||||
_cert = None
|
_cert = None
|
||||||
online = False
|
online = False
|
||||||
download_speed = 0
|
download_speed = 0
|
||||||
|
@ -42,10 +44,36 @@ class Node(object):
|
||||||
self.user_id = user.id
|
self.user_id = user.id
|
||||||
key = str(user.id)
|
key = str(user.id)
|
||||||
self.vk = ed25519.VerifyingKey(key, encoding=ENCODING)
|
self.vk = ed25519.VerifyingKey(key, encoding=ENCODING)
|
||||||
self.go_online()
|
|
||||||
logger.debug('new Node %s online=%s', self.user_id, self.online)
|
logger.debug('new Node %s online=%s', self.user_id, self.online)
|
||||||
|
self._q = Queue()
|
||||||
|
Thread.__init__(self)
|
||||||
|
self.daemon = True
|
||||||
|
self.start()
|
||||||
self._ping = PeriodicCallback(self.ping, 120000)
|
self._ping = PeriodicCallback(self.ping, 120000)
|
||||||
self._ping.start()
|
self._ping.start()
|
||||||
|
self.ping()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
with self._app.app_context():
|
||||||
|
while self._running:
|
||||||
|
action = self._q.get()
|
||||||
|
if not self._running:
|
||||||
|
break
|
||||||
|
if action == 'go_online' or not self.online:
|
||||||
|
self._go_online()
|
||||||
|
else:
|
||||||
|
self.online = self.can_connect()
|
||||||
|
|
||||||
|
def join(self):
|
||||||
|
self._running = False
|
||||||
|
self.ping()
|
||||||
|
return Thread.join(self)
|
||||||
|
|
||||||
|
def ping(self):
|
||||||
|
self._q.put('')
|
||||||
|
|
||||||
|
def go_online(self):
|
||||||
|
self._q.put('go_online')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def url(self):
|
def url(self):
|
||||||
|
@ -148,30 +176,26 @@ class Node(object):
|
||||||
|
|
||||||
def can_connect(self):
|
def can_connect(self):
|
||||||
try:
|
try:
|
||||||
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
|
logger.debug('try to connect to %s', self.url)
|
||||||
s.settimeout(1)
|
r = self._opener.open(self.url, timeout=1)
|
||||||
s.connect((self.host, self.port))
|
c = r.read()
|
||||||
s.close()
|
logger.debug('ok')
|
||||||
return True
|
return True
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
logger.debug('failed')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def ping(self):
|
def _go_online(self):
|
||||||
with self._app.app_context():
|
|
||||||
if self.online:
|
|
||||||
self.online = self.can_connect()
|
|
||||||
else:
|
|
||||||
self.go_online()
|
|
||||||
|
|
||||||
def go_online(self):
|
|
||||||
self.resolve()
|
self.resolve()
|
||||||
u = self.user
|
u = self.user
|
||||||
|
logger.debug('go_online peer=%s queued=%s (%s)', u.peered, u.queued, u.id)
|
||||||
if u.peered or u.queued:
|
if u.peered or u.queued:
|
||||||
try:
|
try:
|
||||||
self.online = False
|
self.online = False
|
||||||
logger.debug('type to connect to %s at [%s]:%s', self.user_id, self.host, self.port)
|
logger.debug('try to connect to %s at [%s]:%s', self.user_id, self.host, self.port)
|
||||||
if self.can_connect():
|
if self.can_connect():
|
||||||
|
logger.debug('connected to [%s]:%s', self.host, self.port)
|
||||||
self.online = True
|
self.online = True
|
||||||
if u.queued:
|
if u.queued:
|
||||||
logger.debug('queued peering event pending=%s peered=%s', u.pending, u.peered)
|
logger.debug('queued peering event pending=%s peered=%s', u.pending, u.peered)
|
||||||
|
@ -184,12 +208,14 @@ class Node(object):
|
||||||
self.peering('removePeering')
|
self.peering('removePeering')
|
||||||
if self.online:
|
if self.online:
|
||||||
self.pullChanges()
|
self.pullChanges()
|
||||||
logger.debug('connected to %s', self.user_id)
|
|
||||||
except:
|
except:
|
||||||
logger.debug('failed to connect to %s', self.user_id, exc_info=1)
|
logger.debug('failed to connect to %s', self.user_id, exc_info=1)
|
||||||
self.online = False
|
self.online = False
|
||||||
else:
|
else:
|
||||||
self.online = False
|
self.online = False
|
||||||
|
self.trigger_status()
|
||||||
|
|
||||||
|
def trigger_status(self):
|
||||||
trigger_event('status', {
|
trigger_event('status', {
|
||||||
'id': self.user_id,
|
'id': self.user_id,
|
||||||
'online': self.online
|
'online': self.online
|
||||||
|
@ -210,10 +236,7 @@ class Node(object):
|
||||||
r = self.request('pushChanges', changes)
|
r = self.request('pushChanges', changes)
|
||||||
except:
|
except:
|
||||||
self.online = False
|
self.online = False
|
||||||
trigger_event('status', {
|
self.trigger_status()
|
||||||
'id': self.user_id,
|
|
||||||
'online': self.online
|
|
||||||
})
|
|
||||||
r = False
|
r = False
|
||||||
logger.debug('pushedChanges %s %s', r, self.user_id)
|
logger.debug('pushedChanges %s %s', r, self.user_id)
|
||||||
|
|
||||||
|
@ -230,9 +253,11 @@ class Node(object):
|
||||||
u.save()
|
u.save()
|
||||||
else:
|
else:
|
||||||
logger.debug('peering failed? %s %s', action, r)
|
logger.debug('peering failed? %s %s', action, r)
|
||||||
|
|
||||||
if action in ('cancelPeering', 'rejectPeering', 'removePeering'):
|
if action in ('cancelPeering', 'rejectPeering', 'removePeering'):
|
||||||
self.online = False
|
self.online = False
|
||||||
|
else:
|
||||||
|
self.go_online()
|
||||||
|
trigger_event('peering.%s'%action.replace('Peering', ''), u.json())
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def download(self, item):
|
def download(self, item):
|
||||||
|
@ -336,7 +361,7 @@ class Nodes(Thread):
|
||||||
self._nodes[user_id] = Node(self, User.get_or_create(user_id))
|
self._nodes[user_id] = Node(self, User.get_or_create(user_id))
|
||||||
else:
|
else:
|
||||||
if not self._nodes[user_id].online:
|
if not self._nodes[user_id].online:
|
||||||
self._nodes[user_id].go_online()
|
self._nodes[user_id].ping()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
with self._app.app_context():
|
with self._app.app_context():
|
||||||
|
@ -351,4 +376,6 @@ class Nodes(Thread):
|
||||||
def join(self):
|
def join(self):
|
||||||
self._running = False
|
self._running = False
|
||||||
self._q.put(None)
|
self._q.put(None)
|
||||||
|
for node in self._nodes.values():
|
||||||
|
node.join()
|
||||||
return Thread.join(self)
|
return Thread.join(self)
|
||||||
|
|
|
@ -42,7 +42,7 @@ class CertValidatingHTTPSConnection(httplib.HTTPConnection):
|
||||||
if not self._ValidateCertificateFingerprint(cert):
|
if not self._ValidateCertificateFingerprint(cert):
|
||||||
raise InvalidCertificateException(self.fingerprint, cert,
|
raise InvalidCertificateException(self.fingerprint, cert,
|
||||||
'fingerprint mismatch')
|
'fingerprint mismatch')
|
||||||
logger.debug('CIPHER %s VERSION %s', self.sock.cipher(), self.sock.ssl_version)
|
#logger.debug('CIPHER %s VERSION %s', self.sock.cipher(), self.sock.ssl_version)
|
||||||
|
|
||||||
class VerifiedHTTPSHandler(urllib2.HTTPSHandler):
|
class VerifiedHTTPSHandler(urllib2.HTTPSHandler):
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
|
|
|
@ -76,7 +76,6 @@ class User(db.Model):
|
||||||
|
|
||||||
def update_peering(self, peered, username=None):
|
def update_peering(self, peered, username=None):
|
||||||
was_peering = self.peered
|
was_peering = self.peered
|
||||||
self.queued = True
|
|
||||||
if peered:
|
if peered:
|
||||||
self.pending = ''
|
self.pending = ''
|
||||||
if username:
|
if username:
|
||||||
|
@ -90,6 +89,7 @@ class User(db.Model):
|
||||||
if not was_peering:
|
if not was_peering:
|
||||||
Changelog.record(state.user(), 'addpeer', self.id, self.nickname)
|
Changelog.record(state.user(), 'addpeer', self.id, self.nickname)
|
||||||
self.peered = True
|
self.peered = True
|
||||||
|
self.queued = True
|
||||||
self.save()
|
self.save()
|
||||||
else:
|
else:
|
||||||
self.pending = ''
|
self.pending = ''
|
||||||
|
|
|
@ -86,18 +86,19 @@ oml.ui.findElement = function() {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
submit: function(data) {
|
submit: function(data) {
|
||||||
var scope = oml.$ui.findInSelect.value(),
|
// FIXME: oml.$ui.findInSelect.value() is undefined
|
||||||
|
var scope = oml.$ui.findInSelect.options('value'),
|
||||||
key = oml.$ui.findSelect.value(),
|
key = oml.$ui.findSelect.value(),
|
||||||
conditions = [].concat(
|
conditions = [].concat(
|
||||||
scope == 'list' ? [{
|
scope == 'list' ? [{
|
||||||
key: 'list',
|
key: 'list',
|
||||||
value: ui._list,
|
operator: '==',
|
||||||
operator: '=='
|
value: ui._list
|
||||||
}] : [],
|
}] : [],
|
||||||
scope == 'user' ? [{
|
scope == 'user' ? [{
|
||||||
key: 'list',
|
key: 'list',
|
||||||
value: ui._list.split(':')[0],
|
operator: '==',
|
||||||
operator: '=='
|
value: ui._list.split(':')[0] + ':'
|
||||||
}] : [],
|
}] : [],
|
||||||
data.value ? [{
|
data.value ? [{
|
||||||
key: key,
|
key: key,
|
||||||
|
@ -158,22 +159,29 @@ oml.ui.findElement = function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderFindInSelect() {
|
function renderFindInSelect() {
|
||||||
var scope = !ui._list ? 'all'
|
var items = [
|
||||||
: Ox.endsWith(ui._list, ':') ? 'user'
|
{id: 'all', title: Ox._('Find In: All Libraries')},
|
||||||
: 'list';
|
{id: 'user', title: Ox._('Find In: This Library')},
|
||||||
var $select = Ox.Select({
|
{id: 'list', title: Ox._('Find In: This List')}
|
||||||
|
],
|
||||||
|
scope = !ui._list ? 'all'
|
||||||
|
: Ox.endsWith(ui._list, ':') ? 'user'
|
||||||
|
: 'list',
|
||||||
|
$select = Ox.Select({
|
||||||
items: [
|
items: [
|
||||||
{id: 'all', title: Ox._('Find In: All Libraries')},
|
items[0],
|
||||||
].concat(scope != 'all' ? [
|
].concat(scope != 'all' ? [
|
||||||
{id: 'user', title: Ox._('Find In: This Library')},
|
items[1],
|
||||||
] : []).concat(scope == 'list' ? [
|
] : []).concat(scope == 'list' ? [
|
||||||
{id: 'list', title: Ox._('Find In: This List')}
|
items[2]
|
||||||
] : []),
|
] : []),
|
||||||
|
max: 1,
|
||||||
|
min: 1,
|
||||||
overlap: 'right',
|
overlap: 'right',
|
||||||
style: 'squared',
|
style: 'squared',
|
||||||
title: scope == 'all' ? 'data' : scope,
|
title: scope == 'all' ? 'data' : scope,
|
||||||
type: 'image',
|
type: 'image',
|
||||||
tooltip: Ox._('Find: FIXME'),
|
tooltip: Ox.getObjectById(items, scope).title,
|
||||||
value: scope
|
value: scope
|
||||||
})
|
})
|
||||||
.bindEvent({
|
.bindEvent({
|
||||||
|
|
|
@ -16,7 +16,10 @@ oml.ui.folders = function() {
|
||||||
//overflowY: 'auto',
|
//overflowY: 'auto',
|
||||||
})
|
})
|
||||||
.bindEvent({
|
.bindEvent({
|
||||||
oml_find: selectList
|
oml_find: selectList,
|
||||||
|
oml_showfolder: function() {
|
||||||
|
oml.resizeListFolders();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function getFind(list) {
|
function getFind(list) {
|
||||||
|
@ -120,7 +123,7 @@ oml.ui.folders = function() {
|
||||||
userIndex[user.nickname] = index;
|
userIndex[user.nickname] = index;
|
||||||
|
|
||||||
oml.$ui.folder[index] = Ox.CollapsePanel({
|
oml.$ui.folder[index] = Ox.CollapsePanel({
|
||||||
collapsed: false,
|
collapsed: !ui.showFolder[user.nickname],
|
||||||
extras: [
|
extras: [
|
||||||
oml.ui.statusIcon(user, index),
|
oml.ui.statusIcon(user, index),
|
||||||
{},
|
{},
|
||||||
|
@ -263,6 +266,7 @@ oml.ui.folders = function() {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
oml.resizeListFolders(); // FIXME: DOESN'T WORK
|
||||||
selectList();
|
selectList();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -272,7 +276,6 @@ oml.ui.folders = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
that.updateItems = function(items) {
|
that.updateItems = function(items) {
|
||||||
Ox.print('UPDATE ITEMS', items);
|
|
||||||
var $list;
|
var $list;
|
||||||
if (arguments.length == 0) {
|
if (arguments.length == 0) {
|
||||||
oml.getLists(function(lists) {
|
oml.getLists(function(lists) {
|
||||||
|
@ -306,6 +309,7 @@ oml.ui.folders = function() {
|
||||||
})
|
})
|
||||||
.css({height: items.length * 16 + 'px'})
|
.css({height: items.length * 16 + 'px'})
|
||||||
.size();
|
.size();
|
||||||
|
oml.resizeFolders();
|
||||||
callback && callback();
|
callback && callback();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -316,10 +320,17 @@ oml.ui.folders = function() {
|
||||||
that.updateItems();
|
that.updateItems();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
change: function(data) {
|
||||||
|
Ox.print('got change event')
|
||||||
|
},
|
||||||
'peering.accept': function(data) {
|
'peering.accept': function(data) {
|
||||||
|
Ox.print('peering.accept reload list')
|
||||||
|
Ox.Request.clearCache('getUsers');
|
||||||
that.updateElement();
|
that.updateElement();
|
||||||
},
|
},
|
||||||
'peering.remove': function(data) {
|
'peering.remove': function(data) {
|
||||||
|
Ox.print('peering.remove reload list')
|
||||||
|
Ox.Request.clearCache('getUsers');
|
||||||
that.updateElement();
|
that.updateElement();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,6 +4,8 @@ oml.ui.infoView = function(identifyData) {
|
||||||
|
|
||||||
var ui = oml.user.ui,
|
var ui = oml.user.ui,
|
||||||
|
|
||||||
|
css = getCSS(ui.coverSize),
|
||||||
|
|
||||||
that = Ox.Element()
|
that = Ox.Element()
|
||||||
.addClass('OxTextPage')
|
.addClass('OxTextPage')
|
||||||
.css({overflowY: 'auto'})
|
.css({overflowY: 'auto'})
|
||||||
|
@ -25,7 +27,7 @@ oml.ui.infoView = function(identifyData) {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
left: '16px',
|
left: '16px',
|
||||||
top: '16px',
|
top: '16px',
|
||||||
width: '256px'
|
width: css.cover.width
|
||||||
})
|
})
|
||||||
.appendTo(that),
|
.appendTo(that),
|
||||||
|
|
||||||
|
@ -33,7 +35,7 @@ oml.ui.infoView = function(identifyData) {
|
||||||
.addClass('OxSelectable')
|
.addClass('OxSelectable')
|
||||||
.css({
|
.css({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
left: '288px',
|
left: css.info.left,
|
||||||
right: !identifyData ? '176px' : 16 + Ox.UI.SCROLLBAR_SIZE + 'px',
|
right: !identifyData ? '176px' : 16 + Ox.UI.SCROLLBAR_SIZE + 'px',
|
||||||
top: '16px'
|
top: '16px'
|
||||||
})
|
})
|
||||||
|
@ -55,6 +57,28 @@ oml.ui.infoView = function(identifyData) {
|
||||||
.appendTo(that);
|
.appendTo(that);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getCSS(size, ratio) {
|
||||||
|
var width = Math.round(ratio >= 1 ? size : size * ratio),
|
||||||
|
height = Math.round(ratio <= 1 ? size : size / ratio),
|
||||||
|
left = size == 256 ? Math.floor((size - width) / 2) : 0;
|
||||||
|
return {
|
||||||
|
cover: {
|
||||||
|
width: size + 'px'
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
left: (size == 256 ? size + 32 : width + 48) + 'px'
|
||||||
|
},
|
||||||
|
image: {
|
||||||
|
left: left + 'px',
|
||||||
|
width: width + 'px',
|
||||||
|
height: height + 'px'
|
||||||
|
},
|
||||||
|
reflection: {
|
||||||
|
top: height + 'px'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function getImageSize(size, ratio) {
|
function getImageSize(size, ratio) {
|
||||||
var width = Math.round(ratio >= 1 ? size : size * ratio),
|
var width = Math.round(ratio >= 1 ? size : size * ratio),
|
||||||
height = Math.round(ratio <= 1 ? size : size / ratio),
|
height = Math.round(ratio <= 1 ? size : size / ratio),
|
||||||
|
@ -82,19 +106,6 @@ oml.ui.infoView = function(identifyData) {
|
||||||
|
|
||||||
function identify(data) {
|
function identify(data) {
|
||||||
oml.ui.identifyDialog(data).open();
|
oml.ui.identifyDialog(data).open();
|
||||||
return;
|
|
||||||
$identifyPanel.select('id');
|
|
||||||
$identifyDialog.open();
|
|
||||||
identify(data);
|
|
||||||
function identify(data) {
|
|
||||||
oml.api.identify(data, function(result) {
|
|
||||||
$identifyList.options({
|
|
||||||
items: result.data.items.map(function(item, index) {
|
|
||||||
return Ox.extend(item, {index: index});
|
|
||||||
})
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderMediaButton(data) {
|
function renderMediaButton(data) {
|
||||||
|
@ -213,23 +224,29 @@ oml.ui.infoView = function(identifyData) {
|
||||||
return $element;
|
return $element;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateCover(size, ratio) {
|
function toggleCoverSize(ratio) {
|
||||||
var width = Math.round(ratio >= 1 ? size : size * ratio),
|
var coverSize = ui.coverSize == 256 ? 512 : 256,
|
||||||
height = Math.round(ratio <= 1 ? size : size / ratio),
|
css = getCSS(coverSize, ratio);
|
||||||
left = Math.floor((size - width) / 2);
|
//$cover.animate(css.cover, 250);
|
||||||
$image.css({
|
$info.animate(css.info, 250);
|
||||||
left: left + 'px',
|
$image.animate(css.image, 250);
|
||||||
width: width + 'px',
|
$reflectionImage.animate(css.image, 250);
|
||||||
height: height + 'px'
|
$reflection.animate(css.reflection, 250);
|
||||||
}).show();
|
/*
|
||||||
$reflectionImage.css({
|
$reflectionGradient.animate({
|
||||||
left: left + 'px',
|
width: iconSize + 'px',
|
||||||
width: width + 'px',
|
height: iconSize / 2 + 'px'
|
||||||
height: height + 'px'
|
}, 250);
|
||||||
});
|
*/
|
||||||
$reflection.css({
|
|
||||||
top: height + 'px'
|
oml.UI.set({coverSize: coverSize});
|
||||||
}).show();
|
}
|
||||||
|
|
||||||
|
function updateCover(ratio) {
|
||||||
|
var css = getCSS(ui.coverSize, ratio);
|
||||||
|
$image.css(css.image).show();
|
||||||
|
$reflectionImage.css(css.image);
|
||||||
|
$reflection.css(css.reflection).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
that.updateElement = function(idOrData, $elements) {
|
that.updateElement = function(idOrData, $elements) {
|
||||||
|
@ -257,10 +274,10 @@ oml.ui.infoView = function(identifyData) {
|
||||||
var $mediaButton,
|
var $mediaButton,
|
||||||
isEditable = !data.mainid && data.mediastate == 'available',
|
isEditable = !data.mainid && data.mediastate == 'available',
|
||||||
src = !identifyData
|
src = !identifyData
|
||||||
? '/' + data.id + '/cover256.jpg?' + data.modified
|
? '/' + data.id + '/cover512.jpg?' + data.modified
|
||||||
: data.cover,
|
: data.cover,
|
||||||
ratio = data.coverRatio || oml.config.coverRatio,
|
ratio = data.coverRatio || oml.config.coverRatio,
|
||||||
size = 256,
|
size = ui.coverSize,
|
||||||
reflectionSize = Math.round(size / 2);
|
reflectionSize = Math.round(size / 2);
|
||||||
|
|
||||||
$elements.forEach(function($element) {
|
$elements.forEach(function($element) {
|
||||||
|
@ -269,11 +286,14 @@ oml.ui.infoView = function(identifyData) {
|
||||||
|
|
||||||
if ($element == $cover) {
|
if ($element == $cover) {
|
||||||
|
|
||||||
$image = $('<img>')
|
$image = Ox.Element({
|
||||||
|
element: '<img>',
|
||||||
|
tooltip: '' // TODO
|
||||||
|
})
|
||||||
.on({
|
.on({
|
||||||
load: function() {
|
load: function() {
|
||||||
var ratio = $image[0].width / $image[0].height;
|
ratio = $image[0].width / $image[0].height;
|
||||||
updateCover(size, ratio);
|
updateCover(ratio);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.attr({src: src})
|
.attr({src: src})
|
||||||
|
@ -281,6 +301,11 @@ oml.ui.infoView = function(identifyData) {
|
||||||
position: 'absolute'
|
position: 'absolute'
|
||||||
})
|
})
|
||||||
.hide()
|
.hide()
|
||||||
|
.bindEvent({
|
||||||
|
singleclick: function() {
|
||||||
|
toggleCoverSize(ratio);
|
||||||
|
}
|
||||||
|
})
|
||||||
.appendTo($cover);
|
.appendTo($cover);
|
||||||
|
|
||||||
$reflection = $('<div>')
|
$reflection = $('<div>')
|
||||||
|
|
|
@ -17,7 +17,7 @@ oml.ui.leftPanel = function() {
|
||||||
collapsed: !oml.user.ui.showInfo,
|
collapsed: !oml.user.ui.showInfo,
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
element: oml.$ui.info = oml.ui.info(),
|
element: oml.$ui.info = oml.ui.info(),
|
||||||
size: ui.sidebarSize,
|
size: oml.getInfoHeight(),
|
||||||
tooltip: Ox._('info') + ' <span class="OxBright">'
|
tooltip: Ox._('info') + ' <span class="OxBright">'
|
||||||
+ Ox.SYMBOLS.SHIFT + 'I</span>'
|
+ Ox.SYMBOLS.SHIFT + 'I</span>'
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,15 +12,15 @@ oml.ui.list = function() {
|
||||||
delete oml.$ui.previewDialog;
|
delete oml.$ui.previewDialog;
|
||||||
},
|
},
|
||||||
copy: function(data) {
|
copy: function(data) {
|
||||||
oml.clipboard.copy(data.ids, 'item');
|
oml.clipboard.copy(data.ids, 'book');
|
||||||
},
|
},
|
||||||
copyadd: function(data) {
|
copyadd: function(data) {
|
||||||
oml.clipboard.copy(data.ids, 'item');
|
oml.clipboard.copy(data.ids, 'book');
|
||||||
},
|
},
|
||||||
cut: function(data) {
|
cut: function(data) {
|
||||||
var listData = oml.getListData();
|
var listData = oml.getListData();
|
||||||
if (listData.editable && listData.type == 'static') {
|
if (listData.editable && listData.type == 'static') {
|
||||||
oml.clipboard.copy(data.ids, 'item');
|
oml.clipboard.copy(data.ids, 'book');
|
||||||
oml.doHistory('cut', data.ids, ui._list, function() {
|
oml.doHistory('cut', data.ids, ui._list, function() {
|
||||||
oml.UI.set({listSelection: []});
|
oml.UI.set({listSelection: []});
|
||||||
oml.$ui.folders.updateElement();
|
oml.$ui.folders.updateElement();
|
||||||
|
@ -31,7 +31,7 @@ oml.ui.list = function() {
|
||||||
cutadd: function(data) {
|
cutadd: function(data) {
|
||||||
var listData = oml.getListData();
|
var listData = oml.getListData();
|
||||||
if (listData.editable && listData.type == 'static') {
|
if (listData.editable && listData.type == 'static') {
|
||||||
oml.clipboard.add(data.ids, 'item');
|
oml.clipboard.add(data.ids, 'book');
|
||||||
oml.doHistory('cut', data.ids, ui._list, function() {
|
oml.doHistory('cut', data.ids, ui._list, function() {
|
||||||
oml.UI.set({listSelection: []});
|
oml.UI.set({listSelection: []});
|
||||||
oml.$ui.folders.updateElement();
|
oml.$ui.folders.updateElement();
|
||||||
|
@ -96,6 +96,15 @@ oml.ui.list = function() {
|
||||||
oml.$ui.previewDialog.updateElement();
|
oml.$ui.previewDialog.updateElement();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
paste: function(data) {
|
||||||
|
var items = oml.clipboard.paste();
|
||||||
|
if (items.length && oml.clipboard.type() == 'book' && oml.getListData().editable) {
|
||||||
|
oml.doHistory('paste', items, ui._list, function() {
|
||||||
|
oml.UI.set({listSelection: items});
|
||||||
|
oml.reloadList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
resize: function(data) {
|
resize: function(data) {
|
||||||
// this is the resize event of the split panel
|
// this is the resize event of the split panel
|
||||||
that.size();
|
that.size();
|
||||||
|
|
|
@ -76,7 +76,7 @@ oml.ui.listDialog = function() {
|
||||||
// FIXME: UGLY
|
// FIXME: UGLY
|
||||||
listNames[listNames.indexOf(listData.name)] = value;
|
listNames[listNames.indexOf(listData.name)] = value;
|
||||||
listData.name = value;
|
listData.name = value;
|
||||||
//
|
// ...
|
||||||
oml.api.editList({
|
oml.api.editList({
|
||||||
id: ui._list,
|
id: ui._list,
|
||||||
name: value
|
name: value
|
||||||
|
@ -118,4 +118,4 @@ oml.ui.listDialog = function() {
|
||||||
|
|
||||||
return that;
|
return that;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -379,6 +379,24 @@ oml.ui.mainMenu = function() {
|
||||||
oml.UI.set({listSelection: []});
|
oml.UI.set({listSelection: []});
|
||||||
} else if (id == 'invertselection') {
|
} else if (id == 'invertselection') {
|
||||||
oml.$ui.list.invertSelection();
|
oml.$ui.list.invertSelection();
|
||||||
|
} else if (Ox.contains(['cut', 'cutadd'], id)) {
|
||||||
|
var action = data.id == 'cut' ? 'copy' : 'add';
|
||||||
|
fromMenu = true;
|
||||||
|
oml.clipboard[action](ui.listSelection, 'item');
|
||||||
|
oml.doHistory('cut', ui.listSelection, ui._list, function() {
|
||||||
|
oml.UI.set({listSelection: []});
|
||||||
|
oml.reloadList();
|
||||||
|
});
|
||||||
|
} else if (Ox.contains(['copy', 'copyadd'], id)) {
|
||||||
|
var action = data.id == 'copy' ? 'copy' : 'add';
|
||||||
|
fromMenu = true;
|
||||||
|
oml.clipboard[action](ui.listSelection, 'item');
|
||||||
|
} else if (id == 'paste') {
|
||||||
|
var items = oml.clipboard.paste();
|
||||||
|
oml.doHistory('paste', items, ui._list, function() {
|
||||||
|
oml.UI.set({listSelection: items});
|
||||||
|
oml.reloadList();
|
||||||
|
});
|
||||||
} else if (data.id == 'clearclipboard') {
|
} else if (data.id == 'clearclipboard') {
|
||||||
oml.clipboard.clear();
|
oml.clipboard.clear();
|
||||||
} else if (data.id == 'delete') {
|
} else if (data.id == 'delete') {
|
||||||
|
@ -542,7 +560,7 @@ oml.ui.mainMenu = function() {
|
||||||
canCopy = canSelect && selectionItems,
|
canCopy = canSelect && selectionItems,
|
||||||
canCut = canCopy && listData.editable,
|
canCut = canCopy && listData.editable,
|
||||||
canPaste = listData.editable && clipboardItems,
|
canPaste = listData.editable && clipboardItems,
|
||||||
canAdd = canCopy && clipboardItems && clipboardItemType == ui.section,
|
canAdd = canCopy && clipboardItems && clipboardType == 'book',
|
||||||
canDelete = listData.user == username && selectionItems,
|
canDelete = listData.user == username && selectionItems,
|
||||||
historyItems = oml.history.items(),
|
historyItems = oml.history.items(),
|
||||||
undoText = oml.history.undoText(),
|
undoText = oml.history.undoText(),
|
||||||
|
@ -783,6 +801,24 @@ oml.ui.mainMenu = function() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oml.clipboard.bindEvent(function(data, event) {
|
||||||
|
if (Ox.contains(['add', 'copy', 'clear'], event)) {
|
||||||
|
that.replaceMenu('editMenu', getEditMenu());
|
||||||
|
}
|
||||||
|
if (Ox.contains(['add', 'copy', 'paste'], event) && !fromMenu) {
|
||||||
|
that.highlightMenu('editMenu');
|
||||||
|
}
|
||||||
|
fromMenu = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
oml.history.bindEvent(function(data, event) {
|
||||||
|
that.replaceMenu('editMenu', getEditMenu());
|
||||||
|
if (Ox.contains(['undo', 'redo'], event) && !fromMenu) {
|
||||||
|
that.highlightMenu('editMenu');
|
||||||
|
}
|
||||||
|
fromMenu = false;
|
||||||
|
});
|
||||||
|
|
||||||
that.updateElement = function(menu) {
|
that.updateElement = function(menu) {
|
||||||
(
|
(
|
||||||
menu ? Ox.makeArray(menu) : ['listMenu', 'editMenu', 'findMenu']
|
menu ? Ox.makeArray(menu) : ['listMenu', 'editMenu', 'findMenu']
|
||||||
|
|
|
@ -90,6 +90,9 @@
|
||||||
oml.URL.init().parse(function() {
|
oml.URL.init().parse(function() {
|
||||||
oml.clipboard = Ox.Clipboard();
|
oml.clipboard = Ox.Clipboard();
|
||||||
oml.history = Ox.History();
|
oml.history = Ox.History();
|
||||||
|
Ox.$window.on({
|
||||||
|
resize: oml.resizeWindow
|
||||||
|
});
|
||||||
oml.$ui.appPanel = oml.ui.appPanel().appendTo(Ox.$body);
|
oml.$ui.appPanel = oml.ui.appPanel().appendTo(Ox.$body);
|
||||||
oml.$ui.loadingIcon.updateElement(Ox.Request.requests());
|
oml.$ui.loadingIcon.updateElement(Ox.Request.requests());
|
||||||
Ox.Request.bindEvent({
|
Ox.Request.bindEvent({
|
||||||
|
@ -100,7 +103,7 @@
|
||||||
oml.$ui.loadingIcon.updateElement(data.requests);
|
oml.$ui.loadingIcon.updateElement(data.requests);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (oml.user.preferences.extensions) {
|
if (oml.user.preferences.extensions) {
|
||||||
try {
|
try {
|
||||||
eval(oml.user.preferences.extensions)
|
eval(oml.user.preferences.extensions)
|
||||||
} catch(e) {}
|
} catch(e) {}
|
||||||
|
|
|
@ -17,22 +17,30 @@ oml.ui.rightPanel = function() {
|
||||||
],
|
],
|
||||||
orientation: 'horizontal',
|
orientation: 'horizontal',
|
||||||
selected: !ui.item ? 'list' : 'item',
|
selected: !ui.item ? 'list' : 'item',
|
||||||
size: window.innerWidth - ui.showSidebar * ui.sidebarSize - 1
|
size: getSize()
|
||||||
})
|
})
|
||||||
.bindEvent({
|
.bindEvent({
|
||||||
resize: function(data) {
|
resize: function(data) {
|
||||||
|
Ox.print('::RESIZING', data.size);
|
||||||
that.options({size: data.size});
|
that.options({size: data.size});
|
||||||
oml.$ui.filtersOuterPanel.updateElement();
|
oml.$ui.filtersOuterPanel.updateElement();
|
||||||
oml.$ui.itemViewPanel.options({size: data.size});
|
oml.$ui.itemViewPanel.options({size: data.size});
|
||||||
},
|
},
|
||||||
oml_item: function(data) {
|
oml_item: function(data) {
|
||||||
Ox.print('rightPanel, oml_item', data);
|
|
||||||
if (!!data.value != !!data.previousValue) {
|
if (!!data.value != !!data.previousValue) {
|
||||||
that.options({selected: !ui.item ? 'list' : 'item'});
|
that.options({selected: !ui.item ? 'list' : 'item'});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getSize() {
|
||||||
|
return window.innerWidth - ui.showSidebar * ui.sidebarSize - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
that.updateElement = function() {
|
||||||
|
return that.triggerEvent('resize', {size: getSize()});
|
||||||
|
};
|
||||||
|
|
||||||
return that;
|
return that;
|
||||||
|
|
||||||
};
|
};
|
|
@ -44,21 +44,20 @@ oml.ui.statusIcon = function(user, index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStatus(data) {
|
function getStatus(data) {
|
||||||
return !oml.user.online && index ? 'unknown'
|
return !oml.user.online ? 'unknown'
|
||||||
: data.online ? 'connected'
|
: data.online ? 'connected'
|
||||||
: 'disconnected';
|
: 'disconnected';
|
||||||
}
|
}
|
||||||
|
|
||||||
function render() {
|
function render() {
|
||||||
var color = {
|
var color = {
|
||||||
connected: [[64, 255, 64], [0, 192, 0]],
|
connected: [[64, 255, 64], [0, 192, 0]],
|
||||||
disconnected: [[255, 64, 64], [192, 0, 0]],
|
disconnected: [[255, 64, 64], [192, 0, 0]],
|
||||||
transferring: [[64, 255, 255], [0, 192, 192]],
|
transferring: [[64, 255, 255], [0, 192, 192]],
|
||||||
unknown: [[255, 255, 64], [192, 192, 0]]
|
unknown: [[255, 255, 64], [192, 192, 0]]
|
||||||
}[status].map(function(rgb) {
|
}[status].map(function(rgb) {
|
||||||
return 'rgb(' + rgb.join(', ') + ')';
|
return 'rgb(' + rgb.join(', ') + ')';
|
||||||
}).join(', ');
|
}).join(', ');
|
||||||
|
|
||||||
that.options({
|
that.options({
|
||||||
tooltip: Ox._({
|
tooltip: Ox._({
|
||||||
connected: 'Connected',
|
connected: 'Connected',
|
||||||
|
@ -68,7 +67,6 @@ oml.ui.statusIcon = function(user, index) {
|
||||||
}).css({
|
}).css({
|
||||||
background: '-webkit-linear-gradient(bottom, ' + color + ')',
|
background: '-webkit-linear-gradient(bottom, ' + color + ')',
|
||||||
});
|
});
|
||||||
|
|
||||||
that.find('div').css({
|
that.find('div').css({
|
||||||
background: '-webkit-linear-gradient(top, ' + color + ')',
|
background: '-webkit-linear-gradient(top, ' + color + ')',
|
||||||
});
|
});
|
||||||
|
@ -85,4 +83,5 @@ oml.ui.statusIcon = function(user, index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return that;
|
return that;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -740,9 +740,9 @@ oml.getListData = function(list) {
|
||||||
|
|
||||||
oml.getListFoldersHeight = function() {
|
oml.getListFoldersHeight = function() {
|
||||||
var ui = oml.user.ui;
|
var ui = oml.user.ui;
|
||||||
return Object.keys(ui.showFolder).reduce(function(value, id, index) {
|
return oml.$ui.folder.reduce(function(value, $folder, index) {
|
||||||
var items = oml.$ui.folderList[index].options('items').length;
|
var items = oml.$ui.folderList[index].options('items').length;
|
||||||
return value + 16 + ui.showFolder[id] * (1 + items) * 16;
|
return value + 16 + !$folder.options('collapsed') * (1 + items) * 16;
|
||||||
}, 16);
|
}, 16);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -895,8 +895,7 @@ oml.hasDialogOrScreen = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
oml.reloadList = function() {
|
oml.reloadList = function() {
|
||||||
Ox.print('RELOAD LIST NOT IMPLEMENTED')
|
oml.$ui.list.updateElement();
|
||||||
// ...
|
|
||||||
};
|
};
|
||||||
|
|
||||||
oml.resizeFilters = function() {
|
oml.resizeFilters = function() {
|
||||||
|
@ -905,6 +904,16 @@ oml.resizeFilters = function() {
|
||||||
|
|
||||||
oml.resizeListFolders = function() {
|
oml.resizeListFolders = function() {
|
||||||
// FIXME: does this have to be here?
|
// FIXME: does this have to be here?
|
||||||
|
/*
|
||||||
|
Ox.print(
|
||||||
|
'RESIZE LIST FOLDERS',
|
||||||
|
'SIDEBAR', oml.user.ui.sidebarSize,
|
||||||
|
'WIDTH', oml.getListFoldersWidth(),
|
||||||
|
'HEIGHT', oml.getListFoldersHeight(),
|
||||||
|
'INFO HEIGHT', oml.getInfoHeight(),
|
||||||
|
'AVAILABLE HEIGHT', window.innerHeight - 20 - 24 - 1 - oml.user.ui.showInfo * oml.getInfoHeight()
|
||||||
|
)
|
||||||
|
*/
|
||||||
var width = oml.getListFoldersWidth(),
|
var width = oml.getListFoldersWidth(),
|
||||||
columnWidth = width - 58;
|
columnWidth = width - 58;
|
||||||
oml.$ui.librariesList
|
oml.$ui.librariesList
|
||||||
|
@ -919,19 +928,12 @@ oml.resizeListFolders = function() {
|
||||||
.css({width: width + 'px'})
|
.css({width: width + 'px'})
|
||||||
.resizeColumn('name', columnWidth);
|
.resizeColumn('name', columnWidth);
|
||||||
});
|
});
|
||||||
/*
|
};
|
||||||
oml.$ui.librariesList
|
|
||||||
.$body.find('.OxContent')
|
oml.resizeWindow = function() {
|
||||||
.css({width: width + 'px'});
|
oml.$ui.leftPanel && oml.$ui.leftPanel.size(2, oml.getInfoHeight());
|
||||||
Ox.forEach(oml.$ui.folder, function($folder, index) {
|
oml.resizeListFolders();
|
||||||
oml.$ui.libraryList[index]
|
oml.$ui.rightPanel && oml.$ui.rightPanel.updateElement();
|
||||||
.$body.find('.OxContent')
|
|
||||||
.css({width: width + 'px'});
|
|
||||||
oml.$ui.folderList[index]
|
|
||||||
.$body.find('.OxContent')
|
|
||||||
.css({width: width + 'px'});
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
};
|
};
|
||||||
|
|
||||||
oml.updateFilterMenus = function() {
|
oml.updateFilterMenus = function() {
|
||||||
|
|
Loading…
Add table
Reference in a new issue