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