@@ -114,7 +116,7 @@
ViewRecent.prototype = Object.create(baseView.prototype);
ViewRecent.prototype.constructor = ViewRecent;
utils.fn.extend(ViewRecent.prototype, {
- render: function() {
+ render: function () {
baseView.prototype.render.apply(this, arguments);
if (!localStorage.getItem('welcome')) {
@@ -125,7 +127,7 @@
this.$boxRecent = this.$panel.find('#box-recent');
this.$panelContainer = this.$panel.find('.recent-panel-container');
},
- listitemtemplate: function(info) {
+ listitemtemplate: function (info) {
let id = !!info.uid ? (` id="${info.uid}"`) : '';
info.crypted === undefined && (info.crypted = false);
const dotIndex = info.name.lastIndexOf('.');
@@ -144,7 +146,8 @@
-
-
+
${info.descr}
`;
+ //language=HTML
+ _tpl += `
+
+
+
`;
+
if (info.type !== 'folder') {
- _tpl += `
`;
- _tpl += `
-
-
`;
+ //language=HTML
+ _tpl += `
+
`;
+
+ //language=HTML
+ _tpl += `
+
+
+
`;
}
return _tpl + '
';
},
onscale: function (pasteSvg) {
- let elm,icoName, parent,
+ let elm, icoName, parent,
emptylist = $('[class*="text-emptylist"]', '#box-recent');
emptylist.toggleClass('text-emptylist text-emptylist-svg');
- if(pasteSvg && !emptylist.find('svg').length)
+ if (pasteSvg && !emptylist.find('svg').length)
emptylist.prepend($('
'));
// todo: rewrite cicon rescale
@@ -252,26 +273,26 @@
window.ControllerRecent = ControllerRecent;
- String.prototype.hashCode = function() {
+ String.prototype.hashCode = function () {
var hash = 0, i, chr;
if (this.length === 0) return hash;
for (i = this.length; !(--i < 0);) {
- chr = this.charCodeAt(i);
- hash = ((hash << 5) - hash) + chr;
- hash = hash & hash; // Convert to 32bit integer
+ chr = this.charCodeAt(i);
+ hash = ((hash << 5) - hash) + chr;
+ hash = hash & hash; // Convert to 32bit integer
}
return hash;
};
- utils.fn.extend(ControllerRecent.prototype, (function() {
+ utils.fn.extend(ControllerRecent.prototype, (function () {
let collectionRecents, collectionRecovers;
let ppmenu;
const ITEMS_LOAD_RANGE = 40;
const _add_recent_block = function () {
- if ( !this.rawRecents || !Object.keys(this.rawRecents).length ) return;
+ if (!this.rawRecents || !Object.keys(this.rawRecents).length) return;
const _raw_block = this.rawRecents.slice(this.recentIndex, this.recentIndex + ITEMS_LOAD_RANGE);
const _files = utils.fn.parseRecent(_raw_block);
@@ -282,22 +303,22 @@
var model = new FileModel(item);
model.set('hash', item.path.hashCode());
- if ( !!this.rawRecents ) {
+ if (!!this.rawRecents) {
collectionRecents.add(model);
_check_block[model.get('hash')] = item.path;
} else return;
}
const _new_items_count = Object.keys(_check_block).length;
- if ( _new_items_count ) {
- if ( this.appready ) {
+ if (_new_items_count) {
+ if (this.appready) {
sdk.execCommand('files:check', JSON.stringify(_check_block));
}
Object.assign(this.check_list, _check_block);
}
- if ( _new_items_count == ITEMS_LOAD_RANGE ) {
+ if (_new_items_count === ITEMS_LOAD_RANGE) {
setTimeout(e => {
this.recentIndex += ITEMS_LOAD_RANGE;
_add_recent_block.call(this);
@@ -307,7 +328,6 @@
}
// this.view.$boxRecent.css('display', collectionRecents.size() > 0 ? 'flex' : 'none');
- // requestAnimationFrame(() => this.view.updateListSize());
if (collectionRecents.size() > 0 || collectionRecovers.size() > 0) {
this.dndZone.hide();
@@ -315,7 +335,7 @@
}
};
- var _on_recents = function(params) {
+ var _on_recents = function (params) {
this.rawRecents = undefined;
setTimeout(e => {
@@ -348,6 +368,12 @@
};
function addContextMenuEventListener(collection, model, view, actionList) {
+ $(`#${model.uid}-pin-btn`, view).click((e) => {
+ e.stopPropagation();
+ const pinned = !model.pinned;
+ model.setMany({ pinned: pinned, pinid: pinned ? -model.fileid : model.fileid });
+ })
+
$(`#${model.uid}-more-btn`, view).click((e) => {
e.stopPropagation();
@@ -356,6 +382,18 @@
if (m.uid != model.uid)
Menu.closeAll();
}
+ ppmenu.actionlist = actionList;
+ if (actionList === 'recovery') {
+ ppmenu.hideItem('files:explore', true);
+ ppmenu.hideItem('files:pin', true);
+ ppmenu.hideItem('files:unpin', true);
+ } else {
+ ppmenu.hideItem('files:explore', (!model.islocal && !model.dir) || !model.exist);
+ ppmenu.hideItem(model.pinned ? 'files:pin' : 'files:unpin', true);
+ ppmenu.hideItem(model.pinned ? 'files:unpin' : 'files:pin', false);
+ }
+
+ ppmenu.showUnderElem(e.currentTarget, model, $('body').hasClass('rtl') ? 'left' : 'right');
if (!Menu.opened) {
ppmenu.actionlist = actionList;
@@ -366,6 +404,24 @@
})
}
+ function handlePin(collection, model) {
+ let $el = $('#' + model.uid, collection.list);
+ if ($el.length) {
+ const f = collection.items.find((elem) => {
+ return model.pinid <= 0 ? elem.pinid < model.pinid : elem.pinid > model.pinid
+ });
+
+ if (f) {
+ const $item = $('#' + f.uid, collection.list);
+ $el.insertBefore($item);
+ } else if (!f && model.pinid > 0) {
+ $el.appendTo(collection.list);
+ } else {
+ $el.prependTo(collection.list);
+ }
+ }
+ }
+
function _init_collections() {
let _cl_rcbox = this.view.$boxRecent,
_cl_rvbox = this.view.$boxRecovery;
@@ -380,9 +436,20 @@
});
collectionRecents.events.inserted.attach((collection, model) => {
- let $item = this.view.listitemtemplate(model);
+ let $item = $(this.view.listitemtemplate(model));
- collection.list.append($item);
+ if (model.pinned) {
+ const $pinned = collection.list.children('.row.pinned');
+ if ($pinned.length) {
+ $item.insertAfter($pinned.last());
+ } else {
+ $item.prependTo(collection.list);
+ }
+ } else {
+ collection.list.append($item);
+ }
+
+ $item[model.pinned ? 'addClass' : 'removeClass']('pinned');
addContextMenuEventListener(collection, model, this.view.$panel, 'recent');
@@ -392,21 +459,33 @@
collectionRecents.events.click.attach((collection, model) => {
// var _portal = model.descr;
// if ( !model.islocal && !app.controller.portals.isConnected(_portal) ) {
- // app.controller.portals.authorizeOn(_portal, {type: 'fileid', id: model.fileid});
+ // app.controller.portals.authorizeOn(_portal, {type: 'fileid', id: model.fileid});
// } else {
- openFile(OPEN_FILE_RECENT, model);
+ openFile(OPEN_FILE_RECENT, model);
// }
});
- collectionRecents.events.contextmenu.attach(function(collection, model, e){
+ collectionRecents.events.contextmenu.attach(function (collection, model, e) {
ppmenu.actionlist = 'recent';
ppmenu.hideItem('files:explore', (!model.islocal && !model.dir) || !model.exist);
+ ppmenu.hideItem(model.pinned ? 'files:pin' : 'files:unpin', true);
+ ppmenu.hideItem(model.pinned ? 'files:unpin' : 'files:pin', false);
ppmenu.show({left: e.clientX, top: e.clientY}, model);
});
- collectionRecents.events.changed.attach(function(collection, model){
+ collectionRecents.events.changed.attach(function (collection, model, property) {
let $el = collection.list.find('#' + model.uid);
- if ( $el ) $el[model.exist ? 'removeClass' : 'addClass']('unavail');
+ if ($el) {
+ $el[model.exist ? 'removeClass' : 'addClass']('unavail');
+ if (property['pinned'] !== undefined) {
+ sdk.setRecentFilePinned(model.get('fileid'), property['pinned']);
+ $el[model.pinned ? 'addClass' : 'removeClass']('pinned');
+ }
+
+ if (property.pinid != undefined) {
+ handlePin(collection, model);
+ }
+ }
});
collectionRecents.empty();
@@ -417,16 +496,18 @@
view: _cl_rvbox,
list: _cl_rvbox.find('.file-list-body')
});
- collectionRecovers.events.inserted.attach((collection, model)=>{
- collection.list.append( this.view.listitemtemplate(model) );
+ collectionRecovers.events.inserted.attach((collection, model) => {
+ collection.list.append(this.view.listitemtemplate(model));
addContextMenuEventListener(collection, model, this.view.$panel, 'recovery');
});
- collectionRecovers.events.click.attach((collection, model)=>{
+ collectionRecovers.events.click.attach((collection, model) => {
openFile(OPEN_FILE_RECOVERY, model);
});
- collectionRecovers.events.contextmenu.attach((collection, model, e)=>{
+ collectionRecovers.events.contextmenu.attach((collection, model, e) => {
ppmenu.actionlist = 'recovery';
ppmenu.hideItem('files:explore', true);
+ ppmenu.hideItem('files:pin', true);
+ ppmenu.hideItem('files:unpin', true);
ppmenu.show({left: e.clientX, top: e.clientY}, model);
});
};
@@ -437,11 +518,13 @@
className: 'with-icons',
bottomlimitoffset: 10,
items: [
- { caption: utils.Lang.menuFileOpen, action: 'files:open' , icon: '#folder'},
- { caption: utils.Lang.menuFileExplore, action: 'files:explore', icon: '#gofolder' },
- { caption: utils.Lang.menuRemoveModel, action: 'files:forget', icon: '#remove' },
- { caption: '--' },
- { caption: utils.Lang.menuClear, action: 'files:clear', variant: 'negative' }
+ {caption: utils.Lang.menuFileOpen, action: 'files:open', icon: '#folder'},
+ {caption: utils.Lang.menuFilePin, action: 'files:pin', icon: '#pin20'},
+ {caption: utils.Lang.menuFileUnpin, action: 'files:unpin', icon: '#unpin20'},
+ {caption: utils.Lang.menuFileExplore, action: 'files:explore', icon: '#gofolder'},
+ {caption: utils.Lang.menuRemoveModel, action: 'files:forget', icon: '#remove'},
+ {caption: '--'},
+ {caption: utils.Lang.menuClear, action: 'files:clear', variant: 'negative'}
]
});
@@ -454,6 +537,16 @@
menu.actionlist == 'recent' ?
openFile(OPEN_FILE_RECENT, data) :
openFile(OPEN_FILE_RECOVERY, data);
+ } else if (/\:pin/.test(action)) {
+ const targetModel = collectionRecents.find('uid', data.uid);
+ if (targetModel) {
+ targetModel.setMany({ pinned: true, pinid: -targetModel.fileid });
+ }
+ } else if (/\:unpin/.test(action)) {
+ const targetModel = collectionRecents.find('uid', data.uid);
+ if (targetModel) {
+ targetModel.setMany({ pinned: false, pinid: targetModel.fileid });
+ }
} else if (/\:clear/.test(action)) {
if (menu.actionlist === 'recent') {
window.sdk.LocalFileRemoveAllRecents();
@@ -466,8 +559,7 @@
this.dndZone.show();
}
}
- } else
- if (/\:forget/.test(action)) {
+ } else if (/\:forget/.test(action)) {
$('#' + data.uid, this.view.$panel).addClass('lost');
const count = collectionRecovers.size() + collectionRecents.size();
@@ -480,10 +572,13 @@
if ( !(count > 1) ) {
this.dndZone.show();
}
- } else
- if (/\:explore/.test(action)) {
+ } else if (/\:explore/.test(action)) {
if (menu.actionlist == 'recent') {
- sdk.execCommand('files:explore', JSON.stringify({path: data.path, id: data.fileid, hash: data.hash}));
+ sdk.execCommand('files:explore', JSON.stringify({
+ path: data.path,
+ id: data.fileid,
+ hash: data.hash
+ }));
}
}
};
@@ -493,7 +588,7 @@
console.log('on recents filter', e.target.value)
const _filter = e.target.value;
- if ( !_filter.length ) {
+ if (!_filter.length) {
$('.table-files tr.hidden', this.view.$panel).removeClass('hidden')
collectionRecents.items.forEach(model => model.set('hidden', false));
@@ -501,11 +596,10 @@
const re = new RegExp(_filter, "gi");
collectionRecents.items.forEach(model => {
const _path = model.get('path');
- if ( !re.test(_path) ) {
+ if (!re.test(_path)) {
$('#' + model.uid, this.view.$panel).addClass('hidden');
model.set('hidden', true);
- } else
- if ( model.get('hidden') ) {
+ } else if (model.get('hidden')) {
$('#' + model.uid, this.view.$panel).removeClass('hidden');
model.set('hidden', false);
}
@@ -515,7 +609,7 @@
return {
- init: function() {
+ init: function () {
baseController.prototype.init.apply(this, arguments);
this.view.render();
@@ -526,25 +620,23 @@
window.sdk.on('onupdaterecents', _on_recents.bind(this));
window.sdk.on('onupdaterecovers', _on_recovers.bind(this));
- window.sdk.on('on_native_message', (cmd, param)=>{
+ window.sdk.on('on_native_message', (cmd, param) => {
if (/files:checked/.test(cmd)) {
let fobjs = JSON.parse(param);
- if ( fobjs ) {
+ if (fobjs) {
for (let obj in fobjs) {
let value = JSON.parse(fobjs[obj]);
let model = collectionRecents.find('hash', parseInt(obj));
- if ( model ) {
+ if (model) {
model.get('exist') != value && model.set('exist', value);
}
}
}
- } else
- if (/file\:skip/.test(cmd)) {
+ } else if (/file\:skip/.test(cmd)) {
sdk.LocalFileRemoveRecent(parseInt(param));
- } else
- if (/app\:ready/.test(cmd)) {
- if ( Object.keys(this.check_list).length ) {
- setTimeout(()=>{
+ } else if (/app\:ready/.test(cmd)) {
+ if (Object.keys(this.check_list).length) {
+ setTimeout(() => {
sdk.execCommand('files:check', JSON.stringify(this.check_list));
}, 100);
}
@@ -553,11 +645,9 @@
}
});
- // $(window).resize(() => requestAnimationFrame(() => this.view.updateListSize()));
-
CommonEvents.on("icons:svg", this.view.onscale);
- CommonEvents.on('portal:authorized', (data)=>{
- if ( data.type == 'fileid' ) {
+ CommonEvents.on('portal:authorized', (data) => {
+ if (data.type == 'fileid') {
let fileid = data.id;
// openFile(OPEN_FILE_RECENT, fileid);
}
@@ -632,10 +722,10 @@
return this;
},
- getRecents: function() {
+ getRecents: function () {
return collectionRecents;
},
- getRecovers: function() {
+ getRecovers: function () {
return collectionRecovers;
}
};
diff --git a/common/loginpage/src/panels.js b/common/loginpage/src/panels.js
index a40a36067..e546e2be7 100644
--- a/common/loginpage/src/panels.js
+++ b/common/loginpage/src/panels.js
@@ -194,12 +194,14 @@ $(document).ready(function() {
function onActionClick(e) {
var $el = $(this);
var action = $el.attr('action');
+ const pinned = JSON.parse(localStorage.getItem('pinnedFolders') || '[]');
if (/^custom/.test(action)) return;
if (action == 'open' &&
!app.controller.recent.getRecents().size() &&
- !app.controller.recent.getRecovers().size())
+ !app.controller.recent.getRecovers().size() &&
+ !pinned.length)
{
openFile(OPEN_FILE_FOLDER, '');
} else {
diff --git a/common/loginpage/src/utils.js b/common/loginpage/src/utils.js
index 1556453af..c7c87def2 100644
--- a/common/loginpage/src/utils.js
+++ b/common/loginpage/src/utils.js
@@ -385,6 +385,20 @@ utils.fn.extend = function(dest, src) {
return dest;
};
+utils.fn.pinnedFolders = function(path, action) {
+ const key = 'pinnedFolders';
+ let pinned = JSON.parse(localStorage.getItem(key) || '[]');
+
+ if (action === 'check') return pinned.includes(path);
+
+ const i = pinned.indexOf(path);
+ if (action === 'toggle') {
+ i === -1 ? pinned.push(path) : pinned.splice(i, 1);
+ }
+
+ localStorage.setItem(key, JSON.stringify(pinned));
+};
+
utils.fn.parseRecent = function(arr, out = 'files') {
var _files_arr = [], _dirs_arr = [];
@@ -401,6 +415,7 @@ utils.fn.parseRecent = function(arr, out = 'files') {
_files_arr.push({
fileid: _f_.id,
+ pinid: !_f_.pin ? _f_.id : -_f_.id,
type: _f_.type,
format: utils.parseFileFormat(_f_.type),
name: name,
@@ -408,6 +423,7 @@ utils.fn.parseRecent = function(arr, out = 'files') {
date: _f_.modifyed,
path: $('
').html(fn).text(),
cloud: _f_.cloud,
+ pinned: _f_.pin,
});
_dirs_arr.indexOf(path) < 0 && _dirs_arr.push(path);
@@ -416,6 +432,13 @@ utils.fn.parseRecent = function(arr, out = 'files') {
if (out == 'files') return _files_arr;
+ const pinned = JSON.parse(localStorage.getItem('pinnedFolders') || '[]');
+ for (const pinnedPath of pinned) {
+ if (!_dirs_arr.includes(pinnedPath)) {
+ _dirs_arr.push(pinnedPath);
+ }
+ }
+
var out_dirs_arr = [];
for (let _d_ of _dirs_arr) {
let name = (!_is_win ? /([^/]+)$/ : /([^\\/]+)$/).exec(_d_)[1],
@@ -426,11 +449,17 @@ utils.fn.parseRecent = function(arr, out = 'files') {
} else
parent = _d_.slice(0, _d_.length - name.length - 1);
+ let pinned = utils.fn.pinnedFolders(_d_, 'check');
+ let id = _d_.hashCode();
+
out_dirs_arr.push({
type: 'folder',
full: _d_,
name: name,
- descr: parent
+ descr: parent,
+ pinid: !pinned ? id : -id,
+ pinned: pinned,
+ uid: `folder-${id}`
});
}