diff --git a/resources/celerity/map.php b/resources/celerity/map.php --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -8,7 +8,7 @@ return array( 'names' => array( 'core.pkg.css' => 'c2c68e64', - 'core.pkg.js' => 'dc4959a8', + 'core.pkg.js' => '863e6dc5', 'darkconsole.pkg.js' => 'df001cab', 'differential.pkg.css' => '4a93db37', 'differential.pkg.js' => '7528cfc9', @@ -452,9 +452,10 @@ 'rsrc/js/core/Notification.js' => '0c6946e7', 'rsrc/js/core/Prefab.js' => 'c11bac49', 'rsrc/js/core/ShapedRequest.js' => '7cbe244b', - 'rsrc/js/core/TextAreaUtils.js' => 'b3ec3cfc', + 'rsrc/js/core/TextAreaUtils.js' => 'e5cbe43f', 'rsrc/js/core/ToolTip.js' => '3915d490', 'rsrc/js/core/behavior-active-nav.js' => 'e379b58e', + 'rsrc/js/core/behavior-alternate-tab-key.js' => 'af38a007', 'rsrc/js/core/behavior-audio-source.js' => '59b251eb', 'rsrc/js/core/behavior-autofocus.js' => '7319e029', 'rsrc/js/core/behavior-choose-control.js' => '6153c708', @@ -551,6 +552,7 @@ 'javelin-behavior-aphlict-dropdown' => 'f51afce0', 'javelin-behavior-aphlict-listen' => 'a826c925', 'javelin-behavior-aphlict-status' => '58f7803f', + 'javelin-behavior-aphront-alternate-tab-key' => 'af38a007', 'javelin-behavior-aphront-basic-tokenizer' => 'b3a4b884', 'javelin-behavior-aphront-crop' => 'fa0f4fc2', 'javelin-behavior-aphront-drag-and-drop-textarea' => '92eb531d', @@ -746,7 +748,7 @@ 'phabricator-slowvote-css' => '266df6a1', 'phabricator-source-code-view-css' => '7d346aa4', 'phabricator-standard-page-view' => '517cdfb1', - 'phabricator-textareautils' => 'b3ec3cfc', + 'phabricator-textareautils' => 'e5cbe43f', 'phabricator-tooltip' => '3915d490', 'phabricator-transaction-view-css' => '5d0cae25', 'phabricator-ui-example-css' => '528b19de', @@ -1569,6 +1571,11 @@ 3 => 'javelin-dom', 4 => 'javelin-vector', ), + 'af38a007' => array( + 0 => 'javelin-behavior', + 1 => 'javelin-dom', + 2 => 'phabricator-textareautils', + ), 'b1f0ccee' => array( 0 => 'javelin-install', 1 => 'javelin-dom', @@ -1587,9 +1594,6 @@ 'b3e7d692' => array( 0 => 'javelin-install', ), - 'b3ec3cfc' => array( - 0 => 'javelin-install', - ), 'b42eddc7' => array( 0 => 'javelin-install', 1 => 'javelin-dom', @@ -1819,6 +1823,9 @@ 2 => 'javelin-view-visitor', 3 => 'javelin-util', ), + 'e5cbe43f' => array( + 0 => 'javelin-install', + ), 'e614d22b' => array( 0 => 'javelin-install', 1 => 'javelin-dom', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2195,6 +2195,7 @@ 'PhabricatorSettingsPanelDeveloperPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelDeveloperPreferences.php', 'PhabricatorSettingsPanelDiffPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelDiffPreferences.php', 'PhabricatorSettingsPanelDisplayPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelDisplayPreferences.php', + 'PhabricatorSettingsPanelEditingPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelEditingPreferences.php', 'PhabricatorSettingsPanelEmailAddresses' => 'applications/settings/panel/PhabricatorSettingsPanelEmailAddresses.php', 'PhabricatorSettingsPanelEmailPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelEmailPreferences.php', 'PhabricatorSettingsPanelExternalAccounts' => 'applications/settings/panel/PhabricatorSettingsPanelExternalAccounts.php', @@ -4610,6 +4611,7 @@ 'PhabricatorMetaMTAMailingList' => array( 0 => 'PhabricatorMetaMTADAO', 1 => 'PhabricatorPolicyInterface', + 2 => 'PhabricatorDestructableInterface', ), 'PhabricatorMetaMTAMemberQuery' => 'PhabricatorQuery', 'PhabricatorMetaMTAPermanentFailureException' => 'Exception', @@ -5039,6 +5041,7 @@ 'PhabricatorSettingsPanelDeveloperPreferences' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelDiffPreferences' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelDisplayPreferences' => 'PhabricatorSettingsPanel', + 'PhabricatorSettingsPanelEditingPreferences' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelEmailAddresses' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelEmailPreferences' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelExternalAccounts' => 'PhabricatorSettingsPanel', @@ -5483,6 +5486,7 @@ 2 => 'PhabricatorSubscribableInterface', 3 => 'PhabricatorFlaggableInterface', 4 => 'PhabricatorTokenReceiverInterface', + 5 => 'PhabricatorDestructableInterface', ), 'PhrictionDocumentController' => 'PhrictionController', 'PhrictionDocumentEditor' => 'PhabricatorEditor', diff --git a/src/applications/settings/panel/PhabricatorSettingsPanelEditingPreferences.php b/src/applications/settings/panel/PhabricatorSettingsPanelEditingPreferences.php new file mode 100644 --- /dev/null +++ b/src/applications/settings/panel/PhabricatorSettingsPanelEditingPreferences.php @@ -0,0 +1,68 @@ +getUser(); + $preferences = $user->loadPreferences(); + + $pref_tab_indent = PhabricatorUserPreferences::PREFERENCE_TAB_INSERTS_INDENT; + + if ($request->isFormPost()) { + $tab_indent = $request->getInt($pref_tab_indent); + + if ($tab_indent && !$preferences->getPreference($pref_tab_indent)) { + $preferences->setPreference( + $pref_tab_indent, + false); + } + + $preferences->setPreference($pref_tab_indent, $tab_indent); + + $preferences->save(); + return id(new AphrontRedirectResponse()) + ->setURI($this->getPanelURI('?saved=true')); + } + + $form = id(new AphrontFormView()) + ->setUser($user) + ->appendChild( + id(new AphrontFormSelectControl()) + ->setLabel(pht('Tab key inserts indent')) + ->setName($pref_tab_indent) + ->setValue($preferences->getPreference($pref_tab_indent)) + ->setOptions( + array( + 0 => pht('Disabled'), + 1 => pht('Enabled'), + )) + ->setCaption( + pht('When editing text using remarkup text areas, you can press'. + 'tab to insert an indent character.'))) + ->appendChild( + id(new AphrontFormSubmitControl()) + ->setValue(pht('Save Preferences'))); + + $form_box = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Editing Preferences')) + ->setFormSaved($request->getBool('saved')) + ->setForm($form); + + return array( + $form_box, + ); + } +} diff --git a/src/applications/settings/storage/PhabricatorUserPreferences.php b/src/applications/settings/storage/PhabricatorUserPreferences.php --- a/src/applications/settings/storage/PhabricatorUserPreferences.php +++ b/src/applications/settings/storage/PhabricatorUserPreferences.php @@ -8,6 +8,7 @@ const PREFERENCE_MULTIEDIT = 'multiedit'; const PREFERENCE_TITLES = 'titles'; const PREFERENCE_MONOSPACED_TEXTAREAS = 'monospaced-textareas'; + const PREFERENCE_TAB_INSERTS_INDENT = 'tab-insert-indent'; const PREFERENCE_TIME_FORMAT = 'time-format'; const PREFERENCE_RE_PREFIX = 're-prefix'; diff --git a/src/view/form/control/PhabricatorRemarkupControl.php b/src/view/form/control/PhabricatorRemarkupControl.php --- a/src/view/form/control/PhabricatorRemarkupControl.php +++ b/src/view/form/control/PhabricatorRemarkupControl.php @@ -34,6 +34,7 @@ 'uri' => '/file/dropupload/', )); + Javelin::initBehavior( 'phabricator-remarkup-assist', array( @@ -196,6 +197,20 @@ } } + if ($user) { + $tab_indents = $user + ->loadPreferences() + ->getPreference( + PhabricatorUserPreferences::PREFERENCE_TAB_INSERTS_INDENT); + if ($tab_indents == true) { + Javelin::initBehavior( + 'aphront-alternate-tab-key', + array( + 'target' => $id + )); + } + } + $this->setCustomClass( 'remarkup-assist-textarea '.$monospaced_textareas_class); diff --git a/webroot/rsrc/js/core/TextAreaUtils.js b/webroot/rsrc/js/core/TextAreaUtils.js --- a/webroot/rsrc/js/core/TextAreaUtils.js +++ b/webroot/rsrc/js/core/TextAreaUtils.js @@ -44,6 +44,16 @@ area.value = v; JX.TextAreaUtils.setSelectionRange(area, r.start, r.start + text.length); + }, + + insertText : function(area, text) { + var v = area.value; + var r = JX.TextAreaUtils.getSelectionRange(area); + + v = v.substring(0, r.start) + text + v.substring(r.end, v.length); + area.value = v; + + JX.TextAreaUtils.setSelectionRange(area, r.start + text.length, r.start + text.length); } } }); diff --git a/webroot/rsrc/js/core/behavior-alternate-tab-key.js b/webroot/rsrc/js/core/behavior-alternate-tab-key.js new file mode 100644 --- /dev/null +++ b/webroot/rsrc/js/core/behavior-alternate-tab-key.js @@ -0,0 +1,20 @@ +/** + * @provides javelin-behavior-aphront-alternate-tab-key + * @requires javelin-behavior + * javelin-dom + * phabricator-textareautils + */ + +JX.behavior('aphront-alternate-tab-key', function(config) { + var target = JX.$(config.target); + + function handleKeyDown (e) { + if(e.getSpecialKey () == 'tab') { + JX.TextAreaUtils.insertText(target, " "); + e.prevent(); + return false; + } + }; + + JX.DOM.listen(target, 'keydown', null, handleKeyDown); +});