diff --git a/build_data.js b/build_data.js index 2e6948e73..4c4f2bf5e 100644 --- a/build_data.js +++ b/build_data.js @@ -60,7 +60,8 @@ function buildData() { 'fas-i-cursor': {}, 'fas-lock': {}, 'fas-long-arrow-alt-right': {}, - 'fas-th-list': {} + 'fas-th-list': {}, + 'fas-user-cog': {} }; // The Noun Project icons used diff --git a/css/80_app.css b/css/80_app.css index f630d929b..4a5430e1d 100644 --- a/css/80_app.css +++ b/css/80_app.css @@ -3100,17 +3100,6 @@ div.full-screen > button:hover { /* Background / Map Data / Help Pane buttons ------------------------------------------------------- */ -.help-control > button { - border-radius: 0 0 0 4px; -} -[dir='rtl'] .help-control > button { - border-radius: 0 0 4px 0; -} - -.map-data-control button { - border-radius: 0; -} - .background-control > button { border-radius: 4px 0 0 0; } @@ -3118,6 +3107,13 @@ div.full-screen > button:hover { border-radius: 0 4px 0 0; } +.help-control > button { + border-radius: 0 0 0 4px; +} +[dir='rtl'] .help-control > button { + border-radius: 0 0 4px 0; +} + /* Background / Map Data Settings ------------------------------------------------------- */ diff --git a/data/core.yaml b/data/core.yaml index fce243354..bd54547aa 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -731,6 +731,16 @@ en: url: instructions: "Enter a data file URL or vector tile URL template. Valid tokens are:\n {zoom} or {z}, {x}, {y} for Z/X/Y tile scheme" placeholder: Enter a url + preferences: + title: Preferences + description: Preferences + key: P + privacy: + title: Privacy + privacy_link: View the iD privacy policy + third_party_icons: + description: Show Third Party Preset Icons + tooltip: Uncheck this box to avoid loading preset icons from third party sites such as Wikimedia Commons, Facebook, or Twitter. restore: heading: You have unsaved changes description: "Do you wish to restore unsaved changes from a previous editing session?" @@ -1953,6 +1963,7 @@ en: background_switch: "Switch back to last background" map_data: "Toggle map data pane" issues: "Toggle validation issues pane" + preferences: "Toggle user preferences pane" fullscreen: "Enter full screen mode" sidebar: "Toggle sidebar" wireframe: "Toggle wireframe mode" diff --git a/data/shortcuts.json b/data/shortcuts.json index d94344a01..7694073db 100644 --- a/data/shortcuts.json +++ b/data/shortcuts.json @@ -53,6 +53,10 @@ "shortcuts": ["issues.key"], "text": "shortcuts.browsing.display_options.issues" }, + { + "shortcuts": ["preferences.key"], + "text": "shortcuts.browsing.display_options.preferences" + }, { "modifiers": ["⌃", "⌘"], "shortcuts": ["F", "F11"], diff --git a/dist/locales/en.json b/dist/locales/en.json index c2ad73841..b768d6e81 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -925,6 +925,19 @@ } } }, + "preferences": { + "title": "Preferences", + "description": "Preferences", + "key": "P", + "privacy": { + "title": "Privacy", + "privacy_link": "View the iD privacy policy", + "third_party_icons": { + "description": "Show Third Party Preset Icons", + "tooltip": "Uncheck this box to avoid loading preset icons from third party sites such as Wikimedia Commons, Facebook, or Twitter." + } + } + }, "restore": { "heading": "You have unsaved changes", "description": "Do you wish to restore unsaved changes from a previous editing session?", @@ -2405,6 +2418,7 @@ "background_switch": "Switch back to last background", "map_data": "Toggle map data pane", "issues": "Toggle validation issues pane", + "preferences": "Toggle user preferences pane", "fullscreen": "Enter full screen mode", "sidebar": "Toggle sidebar", "wireframe": "Toggle wireframe mode", diff --git a/modules/ui/index.js b/modules/ui/index.js index 2bb8a70c2..2c973f43d 100644 --- a/modules/ui/index.js +++ b/modules/ui/index.js @@ -48,6 +48,7 @@ export { uiNoteComments } from './note_comments'; export { uiNoteEditor } from './note_editor'; export { uiNoteHeader } from './note_header'; export { uiNoteReport } from './note_report'; +export { uiPreferences } from './preferences'; export { uiPresetEditor } from './preset_editor'; export { uiPresetIcon } from './preset_icon'; export { uiPresetList } from './preset_list'; diff --git a/modules/ui/init.js b/modules/ui/init.js index db97dad3e..dce38af71 100644 --- a/modules/ui/init.js +++ b/modules/ui/init.js @@ -29,6 +29,7 @@ import { uiMapData } from './map_data'; import { uiMapInMap } from './map_in_map'; import { uiNotice } from './notice'; import { uiPhotoviewer } from './photoviewer'; +import { uiPreferences } from './preferences'; import { uiRestore } from './restore'; import { uiScale } from './scale'; import { uiShortcuts } from './shortcuts'; @@ -123,6 +124,12 @@ export function uiInit(context) { .attr('class', 'map-control map-issues-control') .call(issues.renderToggleButton); + var preferences = uiPreferences(context); + controls + .append('div') + .attr('class', 'map-control preferences-control') + .call(preferences.renderToggleButton); + var help = uiHelp(context); controls .append('div') @@ -249,6 +256,7 @@ export function uiInit(context) { .call(background.renderPane) .call(mapData.renderPane) .call(issues.renderPane) + .call(preferences.renderPane) .call(help.renderPane); ui.info = uiInfo(context); diff --git a/modules/ui/preferences.js b/modules/ui/preferences.js new file mode 100644 index 000000000..b5ec92c2c --- /dev/null +++ b/modules/ui/preferences.js @@ -0,0 +1,131 @@ +import { event as d3_event, select as d3_select } from 'd3-selection'; + +import { svgIcon } from '../svg/icon'; +import { t, textDirection } from '../util/locale'; +import { tooltip } from '../util/tooltip'; +import { uiDisclosure } from './disclosure'; +import { uiTooltipHtml } from './tooltipHtml'; + + +export function uiPreferences(context) { + const key = t('preferences.key'); + let _pane = d3_select(null); + let _showThirdPartyIcons = context.storage('preferences.privacy.thirdpartyicons') || true; + + const paneTooltip = tooltip() + .placement((textDirection === 'rtl') ? 'right' : 'left') + .html(true) + .title(uiTooltipHtml(t('preferences.description'), key)); + + + function renderPrivacyOptions(selection) { + // enter + let privacyOptionsListEnter = selection.selectAll('.privacy-options-list') + .data([0]) + .enter() + .append('ul') + .attr('class', 'layer-list privacy-options-list'); + + let thirdPartyIconsEnter = privacyOptionsListEnter + .append('li') + .attr('class', 'privacy-third-party-icons-item') + .append('label') + .call(tooltip() + .title(t('preferences.privacy.third_party_icons.tooltip')) + .placement('bottom') + ); + + thirdPartyIconsEnter + .append('input') + .attr('type', 'checkbox') + .on('change', () => { + d3_event.preventDefault(); + _showThirdPartyIcons = !_showThirdPartyIcons; + context.storage('preferences.privacy.thirdpartyicons', _showThirdPartyIcons); + update(); + }); + + thirdPartyIconsEnter + .append('span') + .text(t('preferences.privacy.third_party_icons.description')); + + + // Privacy Policy link + selection.selectAll('.privacy-link') + .data([0]) + .enter() + .append('div') + .attr('class', 'privacy-link') + .append('a') + .attr('target', '_blank') + .call(svgIcon('#iD-icon-out-link', 'inline')) + .attr('href', 'https://github.com/openstreetmap/iD/blob/master/FAQ.md') // TODO replace + .append('span') + .text(t('preferences.privacy.privacy_link')); + + update(); + + + function update() { + selection.selectAll('.privacy-third-party-icons-item') + .classed('active', _showThirdPartyIcons) + .select('input') + .property('checked', _showThirdPartyIcons); + } + } + + + uiPreferences.togglePane = () => { + if (d3_event) d3_event.preventDefault(); + paneTooltip.hide(); + context.ui().togglePanes(!_pane.classed('shown') ? _pane : undefined); + }; + + + uiPreferences.renderToggleButton = (selection) => { + selection + .append('button') + .on('click', uiPreferences.togglePane) + .call(svgIcon('#fas-user-cog', 'light')) + .call(paneTooltip); + }; + + + uiPreferences.renderPane = (selection) => { + _pane = selection + .append('div') + .attr('class', 'fillL map-pane preferences-pane hide') + .attr('pane', 'preferences'); + + let heading = _pane + .append('div') + .attr('class', 'pane-heading'); + + heading + .append('h2') + .text(t('preferences.title')); + + heading + .append('button') + .on('click', () => context.ui().togglePanes()) + .call(svgIcon('#iD-icon-close')); + + + let content = _pane + .append('div') + .attr('class', 'pane-content'); + + content + .append('div') + .attr('class', 'preferences-privacy') + .call(uiDisclosure(context, 'preferences_third_party', true) + .title(t('preferences.privacy.title')) + .content(renderPrivacyOptions) + ); + + context.keybinding() + .on(key, uiPreferences.togglePane); + }; + + return uiPreferences; +} diff --git a/svg/fontawesome/fas-user-cog.svg b/svg/fontawesome/fas-user-cog.svg new file mode 100644 index 000000000..62ae6cfd3 --- /dev/null +++ b/svg/fontawesome/fas-user-cog.svg @@ -0,0 +1 @@ + \ No newline at end of file