diff --git a/ui (gen4)/features/history.js b/ui (gen4)/features/history.js index ab5fc3d1..865d3d9a 100755 --- a/ui (gen4)/features/history.js +++ b/ui (gen4)/features/history.js @@ -419,6 +419,8 @@ var URLHistoryUIActions = actions.Actions({ // - true | undefined - always remove // - flase - never remove // - [ 'open', 'close' ] - explicitly select event + // + // XXX do we need this??? 'url-history-list-clear': ['open', 'close'], // If true pushing the pin item button will also focus the item @@ -636,6 +638,127 @@ var URLHistoryUIActions = actions.Actions({ return o })], + + // XXX need to sort pins... + // XXX need to save pins... + // XXX 'to top' button??? + listURLHistory2: ['History|File/Location history (new)...', + widgets.makeUIDialog(function(){ + var that = this + + var data + var cur = this.location.path + var to_remove = [] + + // save state: + // - save pins and pin order... (XXX) + // - remove stirked out elements... + var save = function(){ + // XXX save pins/order... + data.pins.forEach(function(p){ + //that.toggleURLPinned('on') + }) + + // remove items... + to_remove.forEach(function(e){ + that.dropURLFromHistory(e) + }) + to_remove = [] + } + var makeHistoryList = function(fs_state){ + fs_state = fs_state || {} + var history = Object.keys(that.url_history).reverse() + + // XXX need pin order... + var pinned = [] + var list = history + // NOTE: this might get a little slow for + // very large sets... + .map(function(p){ + // pinned items... + // NOTE: yes direct access is faster, but + // calling the toggler (common API) here + // will isolate the level knowledge to a + // single point which will simplify things + // if anything changes... + //that.url_history[p].pinned ? + // XXX need pin order... + that.toggleURLPinned(p, '?') == 'on' ? + // XXX + pinned.push(p) + : null + + return p + }) + + return { + paths: list, + pins: pinned, + } + } + var makeDisabledChecker = function(fs_state){ + return function(url){ + // see of we need a full refresh or use the + // last fs_state... + if(url in fs_state){ + var d = fs_state[url] + + } else { + var d = !that.checkURLFromHistory(url) + fs_state[url] = d + } + return d + } + } + + // persistent state... + var fs_state = {} + + var dialog = browse.makeLister(null, function(path, make){ + + // live update... + data = data == null ? makeHistoryList(fs_state) : data + + // empty list... + if(data.paths.length == 0){ + make.Action('No history...', {disabled: true}) + + } else { + make.EditablePinnedList(data.paths, data.pins, { + list_id: 'history', + new_item: false, + pins_sortable: true, + + isItemDisabled: makeDisabledChecker(fs_state), + + to_remove: to_remove, + }) + } + + make + .done() + // highlight the current item... + .then(function(){ + dialog + .filter(`"${cur}"`) + .addClass('highlighted') }) + }, + { + selected: cur, + }) + .open(function(evt, path){ + save() + + dialog.close() + + that.openURLFromHistory(path) + }) + .on('close', function(){ + save() + }) + + return dialog + })], }) var URLHistoryUI = diff --git a/ui (gen4)/lib/widget/browse.js b/ui (gen4)/lib/widget/browse.js index 05c1ec6e..481f2800 100755 --- a/ui (gen4)/lib/widget/browse.js +++ b/ui (gen4)/lib/widget/browse.js @@ -395,15 +395,17 @@ function(list){ // // options format: // { -// // test if item is disabled... +// // test if item is disabled/hidden... // // // // NOTE: if this is a string or regexp, this is used via // // .replace(..) so the match will get removed from the item // // text, unless prevented via regexp. // isItemDisabled: | , +// isItemHidden: | , // -// // if true, disabled items will not get created... +// // if true, disabled/hidden items will not get created... // skipDisabledItems: false, +// skipHiddenItems: false, // // // if true, group the items into a element... // groupList: false, @@ -418,48 +420,56 @@ function(data, options){ var res = [] var keys = data instanceof Array ? data : Object.keys(data) options = options || {} - var test = typeof(options.isItemDisabled) == typeof('str') ? - RegExp(options.isItemDisabled) - : options.isItemDisabled + + var predicates = { + disabled: typeof(options.isItemDisabled) == typeof('str') ? + RegExp(options.isItemDisabled) + : options.isItemDisabled, + hidden: typeof(options.isItemHidden) == typeof('str') ? + RegExp(options.isItemHidden) + : options.isItemHidden, + } keys.forEach(function(k){ - var txt = k + var txt var opts = Object.create(options) - if(test){ - txt = k instanceof Array ? k[0] : k + Object.keys(predicates).forEach(function(p){ + var test = predicates[p] - // item passes disabled predicate... - if(test instanceof Function - && test(txt)){ - opts.disabled = true + if(test){ + // check only the first item... + txt = txt || (k instanceof Array ? k[0] : k) - if(options.skipDisabledItems){ - return + // item passes disabled predicate... + if(test instanceof Function + && test(txt)){ + opts[p] = true + + // item matches disabled test... + } else if(test instanceof RegExp + && test.test(txt)){ + var t = txt.replace(test, '') + + opts.disabled = true + + txt = k instanceof Array ? + [t].concat(k.slice(1)) + : t + + // no match -- restore text... + } else { + txt = k } - - // item matches disabled test... - } else if(test instanceof RegExp - && test.test(txt)){ - var t = txt.replace(test, '') - - opts.disabled = true - - txt = k instanceof Array ? - [t].concat(k.slice(1)) - : t - - if(options.skipDisabledItems){ - return - } - - // no match -- restore text... - } else { - txt = k } + }) + + if((opts.disabled && opts.skipDisabledItems) + || (opts.hidden && opts.skipHiddenItems)){ + return } - var elem = make(txt, opts) + var elem = make(txt || k, opts) keys !== data && data[k] && elem.on('open', data[k]) @@ -555,6 +565,10 @@ function(data, options){ // // list length limit is reached... // overflow: function(selected){ ... }, // +// // list if items to remove, if not given this will be maintained +// // internally +// to_remove: null | , +// // // Special buttons... // // // // NOTE: these can be used only if .sort if not set. @@ -644,7 +658,10 @@ function(list, options){ options = options || {} var id = options.list_id || 'default' - var to_remove = dialog.__to_remove[id] = dialog.__to_remove[id] || [] + var to_remove = dialog.__to_remove[id] = + options.to_remove + || dialog.__to_remove[id] + || [] // make a copy of options, to keep it safe from changes we are going // to make... @@ -893,7 +910,9 @@ function(list, options){ // remove items... to_remove.forEach(function(e){ - lst.splice(lst.indexOf(e), 1) + var i = lst.indexOf(e) + i >= 0 + && lst.splice(i, 1) }) // sort... @@ -992,8 +1011,8 @@ function(list, pins, options){ i < 0 ? buttons.push(pin) : (buttons[i] = pin) - options.isItemDisabled = function(e){ return pins.indexOf(e) >= 0 } - options.skipDisabledItems = options.skipDisabledItems !== false ? true : false + options.isItemHidden = function(e){ return pins.indexOf(e) >= 0 } + options.skipHiddenItems = options.skipHiddenItems !== false ? true : false //----------------------------------------- setup options: pins --- var pins_options = { @@ -1001,7 +1020,7 @@ function(list, pins, options){ new_item: false, length_limit: options.pins_length_limit || 10, - isItemDisabled: null, + isItemHidden: null, } pins_options.__proto__ = options var sortable = pins_options.sortable = @@ -1217,6 +1236,7 @@ var BrowserPrototype = { // NOTE: this can be a number indicating the item to select when // load is done. //path: null, + //selected: null, //show_path: true, @@ -1935,7 +1955,8 @@ var BrowserPrototype = { //-------------------------- prepare the path and selection --- // string path and terminated with '/' -- no selection... - if(typeof(path) == typeof('str') && !/[\\\/]/.test(path.trim().slice(-1))){ + if(typeof(path) == typeof('str') + && !/[\\\/]/.test(path.trim().slice(-1))){ path = this.path2list(path) var selection = path.pop() @@ -2341,6 +2362,7 @@ var BrowserPrototype = { make.done = function(){ var s = l.find('.selected') s.length > 0 && that.select(s) + return deferred } make.dialog = this @@ -3586,6 +3608,7 @@ var BrowserPrototype = { // load the initial state... // NOTE: path can be a number so simply or-ing here is a bad idea... var path = options.path != null ? options.path : that.path + var selected = options.selected typeof(path) == typeof(123) ? // select item number... that @@ -3597,9 +3620,16 @@ var BrowserPrototype = { .update(path || '/') // Select the default path... .then(function(){ - // in case we have a manually selected item but that was - // not aligned... - that.selected && that.select() }) + // explicit config selection... + // NOTE: this takes precedence over the path syntax... + // XXX not sure if we need this... + // ...currently this is used only when path is + // a list and we need to also select an item... + selected ? that.select(selected) + // we have a manually selected item but that was + // not aligned... + : that.selected ? that.select() + : null }) }, }