mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-15 05:30:35 +02:00
Move preset favoriting functions from core/context.js to presets/index.js
Make recent presets persistent and compatible with favorite presets
This commit is contained in:
+2
-65
@@ -57,7 +57,7 @@ export function coreContext() {
|
||||
addTranslation('en', dataEn);
|
||||
setLocale('en');
|
||||
|
||||
var dispatch = d3_dispatch('enter', 'exit', 'change', 'favoritePreset');
|
||||
var dispatch = d3_dispatch('enter', 'exit', 'change');
|
||||
|
||||
// https://github.com/openstreetmap/iD/issues/772
|
||||
// http://mathiasbynens.be/notes/localstorage-pattern#comment-9
|
||||
@@ -313,69 +313,6 @@ export function coreContext() {
|
||||
var presets;
|
||||
context.presets = function() { return presets; };
|
||||
|
||||
context.getFavoritePresets = function() {
|
||||
// get favorites from local storage
|
||||
var favs = JSON.parse(context.storage('favorite_presets')) || [
|
||||
// use the generic presets as the default favorites
|
||||
{ id: 'point', geom: 'point'},
|
||||
{ id: 'line', geom: 'line'},
|
||||
{ id: 'area', geom: 'area'}
|
||||
];
|
||||
return favs.filter(function(d) {
|
||||
// iD's presets could have changed since this favorite was saved,
|
||||
// so make sure it's still valid.
|
||||
var preset = presets.item(d.id);
|
||||
if (preset === null) {
|
||||
return false;
|
||||
} else if (preset.geometry.indexOf(d.geom) === -1) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
};
|
||||
function setFavoritePresets(favs) {
|
||||
context.storage('favorite_presets', JSON.stringify(favs));
|
||||
|
||||
//and call update on modes
|
||||
dispatch.call('favoritePreset');
|
||||
}
|
||||
context.favoritePreset = function(preset, geom) {
|
||||
var favs = context.getFavoritePresets();
|
||||
|
||||
//add/remove favorites from local storage
|
||||
if (context.isFavoritePreset(preset, geom)) {
|
||||
favs = favs.filter(function(d) {
|
||||
return !(d.id === preset.id && d.geom === geom);
|
||||
});
|
||||
} else {
|
||||
// only allow 10 favorites
|
||||
if (favs.length === 10) {
|
||||
// remove the last favorite (last in, first out)
|
||||
favs.pop();
|
||||
}
|
||||
// append array
|
||||
favs.push({id: preset.id, geom: geom});
|
||||
}
|
||||
setFavoritePresets(favs);
|
||||
};
|
||||
|
||||
context.isFavoritePreset = function(preset, geom) {
|
||||
var favs = context.getFavoritePresets();
|
||||
return favs.some(function(d) {
|
||||
return d.id === preset.id && d.geom === geom;
|
||||
});
|
||||
};
|
||||
context.moveFavoritePreset = function(fromIndex, toIndex) {
|
||||
if (fromIndex === toIndex) return;
|
||||
|
||||
var favs = context.getFavoritePresets();
|
||||
|
||||
if (fromIndex < 0 || toIndex < 0 ||
|
||||
fromIndex >= favs.length || toIndex >= favs.length) return;
|
||||
|
||||
favs.splice(toIndex, 0, favs.splice(fromIndex, 1)[0]);
|
||||
setFavoritePresets(favs);
|
||||
};
|
||||
|
||||
/* Map */
|
||||
var map;
|
||||
@@ -564,7 +501,7 @@ export function coreContext() {
|
||||
connection = services.osm;
|
||||
background = rendererBackground(context);
|
||||
features = rendererFeatures(context);
|
||||
presets = presetIndex();
|
||||
presets = presetIndex(context);
|
||||
|
||||
if (services.maprules && utilStringQs(window.location.hash).maprules) {
|
||||
var maprules = utilStringQs(window.location.hash).maprules;
|
||||
|
||||
+150
-19
@@ -3,8 +3,8 @@ import _forEach from 'lodash-es/forEach';
|
||||
import _isEmpty from 'lodash-es/isEmpty';
|
||||
import _reject from 'lodash-es/reject';
|
||||
import _uniq from 'lodash-es/uniq';
|
||||
import _uniqWith from 'lodash-es/uniqWith';
|
||||
|
||||
import { dispatch as d3_dispatch } from 'd3-dispatch';
|
||||
import { json as d3_json } from 'd3-request';
|
||||
|
||||
import { data } from '../../data/index';
|
||||
@@ -12,6 +12,7 @@ import { presetCategory } from './category';
|
||||
import { presetCollection } from './collection';
|
||||
import { presetField } from './field';
|
||||
import { presetPreset } from './preset';
|
||||
import { utilRebind } from '../util';
|
||||
|
||||
export { presetCategory };
|
||||
export { presetCollection };
|
||||
@@ -19,15 +20,17 @@ export { presetField };
|
||||
export { presetPreset };
|
||||
|
||||
|
||||
export function presetIndex() {
|
||||
export function presetIndex(context) {
|
||||
// a presetCollection with methods for
|
||||
// loading new data and returning defaults
|
||||
|
||||
var dispatch = d3_dispatch('favoritePreset');
|
||||
|
||||
var all = presetCollection([]);
|
||||
var _defaults = { area: all, line: all, point: all, vertex: all, relation: all };
|
||||
var _fields = {};
|
||||
var _universal = [];
|
||||
var _recentWithGeometry = [];
|
||||
var _favorites, _recents;
|
||||
|
||||
// Index of presets by (geometry, tag key).
|
||||
var _index = {
|
||||
@@ -214,7 +217,8 @@ export function presetIndex() {
|
||||
|
||||
all.init = function() {
|
||||
all.collection = [];
|
||||
_recentWithGeometry = [];
|
||||
_favorites = null;
|
||||
_recents = null;
|
||||
_fields = {};
|
||||
_universal = [];
|
||||
_index = { point: {}, vertex: {}, line: {}, area: {}, relation: {} };
|
||||
@@ -228,7 +232,8 @@ export function presetIndex() {
|
||||
_defaults = { area: all, line: all, point: all, vertex: all, relation: all };
|
||||
_fields = {};
|
||||
_universal = [];
|
||||
_recentWithGeometry = [];
|
||||
_favorites = null;
|
||||
_recents = null;
|
||||
|
||||
// Index of presets by (geometry, tag key).
|
||||
_index = {
|
||||
@@ -270,27 +275,153 @@ export function presetIndex() {
|
||||
};
|
||||
|
||||
all.recent = function() {
|
||||
return presetCollection(_uniq(_recentWithGeometry.map(function(d) {
|
||||
return presetCollection(_uniq(all.getRecents().map(function(d) {
|
||||
return d.preset;
|
||||
})));
|
||||
};
|
||||
|
||||
all.recentWithGeometry = function() {
|
||||
return _recentWithGeometry;
|
||||
};
|
||||
function RibbonItem(preset, geometry, source) {
|
||||
var item = {};
|
||||
item.preset = preset;
|
||||
item.geometry = geometry;
|
||||
item.source = source;
|
||||
|
||||
all.choose = function(preset, geometry) {
|
||||
if (preset.searchable !== false) {
|
||||
var newWithGeometry = {
|
||||
preset: preset,
|
||||
geometry: geometry
|
||||
item.matches = function(preset, geometry) {
|
||||
return item.preset.id === preset.id && item.geometry === geometry;
|
||||
};
|
||||
item.minified = function() {
|
||||
return {
|
||||
pID: item.preset.id,
|
||||
geom: item.geometry
|
||||
};
|
||||
_recentWithGeometry = _uniqWith([newWithGeometry].concat(_recentWithGeometry), function(d1, d2) {
|
||||
return d1.preset === d2.preset && d1.geometry === d2.geometry;
|
||||
});
|
||||
};
|
||||
return item;
|
||||
}
|
||||
|
||||
function ribbonItemForMinified(d, source) {
|
||||
if (d && d.pID && d.geom) {
|
||||
var preset = all.item(d.pID);
|
||||
// iD's presets could have changed since this was saved,
|
||||
// so make sure it's still valid.
|
||||
if (preset && preset.matchGeometry(d.geom)) {
|
||||
return RibbonItem(preset, d.geom, source);
|
||||
}
|
||||
}
|
||||
return all;
|
||||
return null;
|
||||
}
|
||||
|
||||
function setFavorites(items) {
|
||||
_favorites = items;
|
||||
var minifiedItems = items.map(function(d) { return d.minified(); });
|
||||
context.storage('preset_favorites', JSON.stringify(minifiedItems));
|
||||
|
||||
// call update
|
||||
dispatch.call('favoritePreset');
|
||||
}
|
||||
|
||||
all.getFavorites = function() {
|
||||
if (!_favorites) {
|
||||
// fetch from local storage
|
||||
_favorites = (JSON.parse(context.storage('preset_favorites')) || [
|
||||
// use the generic presets as the default favorites
|
||||
{ pID: 'point', geom: 'point'},
|
||||
{ pID: 'line', geom: 'line'},
|
||||
{ pID: 'area', geom: 'area'}
|
||||
]).reduce(function(output, d) {
|
||||
var item = ribbonItemForMinified(d, 'favorite');
|
||||
if (item) output.push(item);
|
||||
return output;
|
||||
}, []);
|
||||
}
|
||||
return _favorites;
|
||||
};
|
||||
|
||||
return all;
|
||||
function setRecents(items) {
|
||||
_recents = items;
|
||||
var minifiedItems = items.map(function(d) { return d.minified(); });
|
||||
context.storage('preset_recents', JSON.stringify(minifiedItems));
|
||||
}
|
||||
|
||||
all.getRecents = function() {
|
||||
if (!_recents) {
|
||||
// fetch from local storage
|
||||
_recents = (JSON.parse(context.storage('preset_recents')) || [])
|
||||
.reduce(function(output, d) {
|
||||
var item = ribbonItemForMinified(d, 'recent');
|
||||
if (item) output.push(item);
|
||||
return output;
|
||||
}, []);
|
||||
}
|
||||
return _recents;
|
||||
};
|
||||
|
||||
all.toggleFavorite = function(preset, geometry) {
|
||||
var favs = all.getFavorites();
|
||||
var favorite = all.isFavorite(preset, geometry);
|
||||
if (favorite) {
|
||||
favs.splice(favs.indexOf(favorite), 1);
|
||||
} else {
|
||||
// only allow 10 favorites
|
||||
if (favs.length === 10) {
|
||||
// remove the last favorite (last in, first out)
|
||||
favs.pop();
|
||||
}
|
||||
// append array
|
||||
favs.push(RibbonItem(preset, geometry, 'favorite'));
|
||||
}
|
||||
setFavorites(favs);
|
||||
};
|
||||
|
||||
all.isFavorite = function(preset, geometry) {
|
||||
var favs = all.getFavorites();
|
||||
for (var index in favs) {
|
||||
if (favs[index].matches(preset, geometry)) {
|
||||
return favs[index];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
all.isRecent = function(preset, geometry) {
|
||||
var items = all.getRecents();
|
||||
for (var index in items) {
|
||||
if (items[index].matches(preset, geometry)) {
|
||||
return items[index];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
all.moveFavorite = function(fromIndex, toIndex) {
|
||||
if (fromIndex === toIndex) return;
|
||||
|
||||
var favs = all.getFavorites();
|
||||
|
||||
if (fromIndex < 0 || toIndex < 0 ||
|
||||
fromIndex >= favs.length || toIndex >= favs.length) return;
|
||||
|
||||
favs.splice(toIndex, 0, favs.splice(fromIndex, 1)[0]);
|
||||
setFavorites(favs);
|
||||
};
|
||||
|
||||
all.setMostRecent = function(preset, geometry) {
|
||||
if (preset.searchable === false) return;
|
||||
|
||||
var items = all.getRecents();
|
||||
var item = all.isRecent(preset, geometry);
|
||||
if (item) {
|
||||
items.splice(items.indexOf(item), 1);
|
||||
} else {
|
||||
item = RibbonItem(preset, geometry, 'recent');
|
||||
}
|
||||
// allow 30 recents
|
||||
if (items.length === 30) {
|
||||
// remove the last favorite (first in, first out)
|
||||
items.pop();
|
||||
}
|
||||
// prepend array
|
||||
items.unshift(item);
|
||||
setRecents(items);
|
||||
};
|
||||
|
||||
return utilRebind(all, dispatch, 'on');
|
||||
}
|
||||
|
||||
+15
-16
@@ -52,7 +52,7 @@ export function uiModes(context) {
|
||||
|
||||
context
|
||||
.on('enter.modes', update)
|
||||
.on('favoritePreset.modes', update);
|
||||
.presets().on('favoritePreset.modes', update);
|
||||
|
||||
update();
|
||||
|
||||
@@ -63,17 +63,16 @@ export function uiModes(context) {
|
||||
context.keybinding().off(i.toString());
|
||||
}
|
||||
|
||||
var favoritePresets = context.getFavoritePresets();
|
||||
var favoritePresets = context.presets().getFavorites();
|
||||
var favoriteModes = favoritePresets.map(function(d, index) {
|
||||
var preset = context.presets().item(d.id);
|
||||
var presetName = preset.name().split(' – ')[0];
|
||||
var markerClass = 'add-preset add-' + d.geom + ' add-preset-' + presetName.replace(/\s+/g, '_')
|
||||
+ '-' + d.geom; // replace spaces with underscores to avoid css interpretation
|
||||
if (preset.isFallback()) {
|
||||
var presetName = d.preset.name().split(' – ')[0];
|
||||
var markerClass = 'add-preset add-' + d.geometry + ' add-preset-' + presetName.replace(/\s+/g, '_')
|
||||
+ '-' + d.geometry; // replace spaces with underscores to avoid css interpretation
|
||||
if (d.preset.isFallback()) {
|
||||
markerClass += ' add-generic-preset';
|
||||
}
|
||||
|
||||
var supportedGeometry = preset.geometry.filter(function(geometry) {
|
||||
var supportedGeometry = d.preset.geometry.filter(function(geometry) {
|
||||
return ['vertex', 'point', 'line', 'area'].indexOf(geometry) !== -1;
|
||||
});
|
||||
var vertexIndex = supportedGeometry.indexOf('vertex');
|
||||
@@ -83,18 +82,18 @@ export function uiModes(context) {
|
||||
}
|
||||
var tooltipTitleID = 'modes.add_preset.title';
|
||||
if (supportedGeometry.length !== 1) {
|
||||
if (preset.setTags({}, d.geom).building) {
|
||||
if (d.preset.setTags({}, d.geometry).building) {
|
||||
tooltipTitleID = 'modes.add_preset.building.title';
|
||||
} else {
|
||||
tooltipTitleID = 'modes.add_preset.' + d.geom + '.title';
|
||||
tooltipTitleID = 'modes.add_preset.' + d.geometry + '.title';
|
||||
}
|
||||
}
|
||||
var favoriteMode = {
|
||||
button: markerClass,
|
||||
title: presetName,
|
||||
description: t(tooltipTitleID, { feature: '<strong>' + presetName + '</strong>' }),
|
||||
preset: preset,
|
||||
geometry: d.geom
|
||||
preset: d.preset,
|
||||
geometry: d.geometry
|
||||
};
|
||||
var keyCode;
|
||||
if (textDirection === 'ltr') {
|
||||
@@ -117,7 +116,7 @@ export function uiModes(context) {
|
||||
}
|
||||
|
||||
var mode;
|
||||
switch (d.geom) {
|
||||
switch (d.geometry) {
|
||||
case 'point':
|
||||
case 'vertex':
|
||||
mode = modeAddPoint(context, favoriteMode);
|
||||
@@ -169,7 +168,7 @@ export function uiModes(context) {
|
||||
context.enter(modeBrowse(context));
|
||||
} else {
|
||||
if (d.preset) {
|
||||
context.presets().choose(d.preset, d.geometry);
|
||||
context.presets().setMostRecent(d.preset, d.geometry);
|
||||
}
|
||||
context.enter(d);
|
||||
}
|
||||
@@ -256,10 +255,10 @@ export function uiModes(context) {
|
||||
var y = d3_event.y - dragOrigin.y;
|
||||
if (y > 50) {
|
||||
// dragged out of the top bar, remove the favorite
|
||||
context.favoritePreset(d.preset, d.geometry);
|
||||
context.presets().toggleFavorite(d.preset, d.geometry);
|
||||
} else if (targetIndex !== null) {
|
||||
// dragged to a new position, reorder
|
||||
context.moveFavoritePreset(index, targetIndex);
|
||||
context.presets().moveFavorite(index, targetIndex);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
@@ -35,7 +35,7 @@ export function uiPresetFavorite(preset, geom, context, klass) {
|
||||
d3_event.stopPropagation();
|
||||
d3_event.preventDefault();
|
||||
|
||||
context.favoritePreset(preset, geom);
|
||||
context.presets().toggleFavorite(preset, geom);
|
||||
|
||||
update();
|
||||
});
|
||||
@@ -45,10 +45,10 @@ export function uiPresetFavorite(preset, geom, context, klass) {
|
||||
|
||||
function update() {
|
||||
_button
|
||||
.classed('active', context.isFavoritePreset(preset, geom));
|
||||
.classed('active', context.presets().isFavorite(preset, geom));
|
||||
}
|
||||
|
||||
context.on('favoritePreset.button-' + preset.id.replace(/[^a-zA-Z\d:]/g, '-') + '-' + geom, update);
|
||||
context.presets().on('favoritePreset.button-' + preset.id.replace(/[^a-zA-Z\d:]/g, '-') + '-' + geom, update);
|
||||
|
||||
return presetFavorite;
|
||||
}
|
||||
|
||||
@@ -388,7 +388,7 @@ export function uiPresetList(context) {
|
||||
item.choose = function() {
|
||||
if (d3_select(this).classed('disabled')) return;
|
||||
|
||||
context.presets().choose(preset, context.geometry(_entityID));
|
||||
context.presets().setMostRecent(preset, context.geometry(_entityID));
|
||||
context.perform(
|
||||
actionChangePreset(_entityID, _currentPreset, preset),
|
||||
t('operations.change_tags.annotation')
|
||||
|
||||
@@ -207,7 +207,7 @@ export function uiSearchAdd(context) {
|
||||
if (value.length) {
|
||||
results = presets.search(value, shownGeometry).collection;
|
||||
} else {
|
||||
var recents = context.presets().recentWithGeometry();
|
||||
var recents = context.presets().getRecents();
|
||||
recents = recents.filter(function(d) {
|
||||
return shownGeometry.indexOf(d.geometry) !== -1;
|
||||
});
|
||||
@@ -504,7 +504,7 @@ export function uiSearchAdd(context) {
|
||||
mode = modeAddArea(context, modeInfo);
|
||||
}
|
||||
search.node().blur();
|
||||
context.presets().choose(preset, geometry);
|
||||
context.presets().setMostRecent(preset, geometry);
|
||||
context.enter(mode);
|
||||
};
|
||||
return item;
|
||||
|
||||
Reference in New Issue
Block a user