@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Modernize pinned homepage applications settings

Summary:
Ref T4103. A few bits here:

- We have an ancient "tiles" preference which was just a fallback from 2-3 years ago. Throw that away.
- Modenize the other pinned stuff. We should likely revisit this after the next homepage update but I just left the actual defaults alone for now.
- Lightly prepare for global default editing.
- Add a "reset to defaults" option.

Test Plan:
- Pinned, unpinned, reordered and reset application homepage order.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T4103

Differential Revision: https://secure.phabricator.com/D16028

+129 -71
+2
src/__phutil_library_map__.php
··· 3008 3008 'PhabricatorPhurlURLTransactionComment' => 'applications/phurl/storage/PhabricatorPhurlURLTransactionComment.php', 3009 3009 'PhabricatorPhurlURLTransactionQuery' => 'applications/phurl/query/PhabricatorPhurlURLTransactionQuery.php', 3010 3010 'PhabricatorPhurlURLViewController' => 'applications/phurl/controller/PhabricatorPhurlURLViewController.php', 3011 + 'PhabricatorPinnedApplicationsSetting' => 'applications/settings/setting/PhabricatorPinnedApplicationsSetting.php', 3011 3012 'PhabricatorPirateEnglishTranslation' => 'infrastructure/internationalization/translation/PhabricatorPirateEnglishTranslation.php', 3012 3013 'PhabricatorPlatformSite' => 'aphront/site/PhabricatorPlatformSite.php', 3013 3014 'PhabricatorPointsEditField' => 'applications/transactions/editfield/PhabricatorPointsEditField.php', ··· 7680 7681 'PhabricatorPhurlURLTransactionComment' => 'PhabricatorApplicationTransactionComment', 7681 7682 'PhabricatorPhurlURLTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 7682 7683 'PhabricatorPhurlURLViewController' => 'PhabricatorPhurlController', 7684 + 'PhabricatorPinnedApplicationsSetting' => 'PhabricatorInternalSetting', 7683 7685 'PhabricatorPirateEnglishTranslation' => 'PhutilTranslation', 7684 7686 'PhabricatorPlatformSite' => 'PhabricatorSite', 7685 7687 'PhabricatorPointsEditField' => 'PhabricatorEditField',
+2 -3
src/applications/home/controller/PhabricatorHomeController.php
··· 15 15 ->withLaunchable(true) 16 16 ->execute(); 17 17 18 - $pinned = $user->loadPreferences()->getPinnedApplications( 19 - $applications, 20 - $user); 18 + $pinned = $user->getUserSetting( 19 + PhabricatorPinnedApplicationsSetting::SETTINGKEY); 21 20 22 21 // Force "Applications" to appear at the bottom. 23 22 $meta_app = 'PhabricatorApplicationsApplication';
+1 -6
src/applications/settings/panel/PhabricatorEditEngineSettingsPanel.php
··· 26 26 ->setIsSelfEdit($is_self) 27 27 ->setProfileURI($profile_uri); 28 28 29 - $preferences = $user->loadPreferences(); 30 - 31 - PhabricatorPolicyFilter::requireCapability( 32 - $viewer, 33 - $preferences, 34 - PhabricatorPolicyCapability::CAN_EDIT); 29 + $preferences = $this->loadTargetPreferences(); 35 30 36 31 $engine->setTargetObject($preferences); 37 32
+61 -29
src/applications/settings/panel/PhabricatorHomePreferencesSettingsPanel.php
··· 16 16 } 17 17 18 18 public function processRequest(AphrontRequest $request) { 19 - $user = $request->getUser(); 20 - $preferences = $user->loadPreferences(); 19 + $viewer = $this->getViewer(); 20 + $preferences = $this->loadTargetPreferences(); 21 + 22 + $pinned_key = PhabricatorPinnedApplicationsSetting::SETTINGKEY; 23 + $pinned = $preferences->getSettingValue($pinned_key); 21 24 22 25 $apps = id(new PhabricatorApplicationQuery()) 23 - ->setViewer($user) 26 + ->setViewer($viewer) 24 27 ->withInstalled(true) 25 28 ->withUnlisted(false) 26 29 ->withLaunchable(true) 27 30 ->execute(); 28 - 29 - $pinned = $preferences->getPinnedApplications($apps, $user); 30 31 31 32 $app_list = array(); 32 33 foreach ($pinned as $app) { ··· 35 36 } 36 37 } 37 38 39 + if ($request->getBool('reset')) { 40 + if ($request->isFormPost()) { 41 + $this->writePinnedApplications($preferences, null); 42 + return id(new AphrontRedirectResponse()) 43 + ->setURI($this->getPanelURI()); 44 + } 45 + 46 + return $this->newDialog() 47 + ->setTitle(pht('Reset Applications')) 48 + ->addHiddenInput('reset', 'true') 49 + ->appendParagraph( 50 + pht('Reset pinned applications to their defaults?')) 51 + ->addSubmitButton(pht('Reset Applications')) 52 + ->addCancelButton($this->getPanelURI()); 53 + } 54 + 55 + 38 56 if ($request->getBool('add')) { 39 57 $options = array(); 40 58 foreach ($apps as $app) { ··· 48 66 $pin = $request->getStr('pin'); 49 67 if (isset($options[$pin]) && !in_array($pin, $pinned)) { 50 68 $pinned[] = $pin; 51 - $preferences->setPreference( 52 - PhabricatorUserPreferences::PREFERENCE_APP_PINNED, 53 - $pinned); 54 - $preferences->save(); 69 + 70 + $this->writePinnedApplications($preferences, $pinned); 55 71 56 72 return id(new AphrontRedirectResponse()) 57 73 ->setURI($this->getPanelURI()); ··· 65 81 ->setDisabledOptions(array_keys($app_list)); 66 82 67 83 $form = id(new AphrontFormView()) 68 - ->setUser($user) 84 + ->setViewer($viewer) 69 85 ->addHiddenInput('add', 'true') 70 86 ->appendRemarkupInstructions( 71 87 pht('Choose an application to pin to your home page.')) 72 88 ->appendChild($options_control); 73 89 74 - $dialog = id(new AphrontDialogView()) 75 - ->setUser($user) 90 + return $this->newDialog() 76 91 ->setWidth(AphrontDialogView::WIDTH_FORM) 77 92 ->setTitle(pht('Pin Application')) 78 93 ->appendChild($form->buildLayoutView()) 79 94 ->addSubmitButton(pht('Pin Application')) 80 95 ->addCancelButton($this->getPanelURI()); 81 - 82 - return id(new AphrontDialogResponse())->setDialog($dialog); 83 96 } 84 97 85 98 $unpin = $request->getStr('unpin'); ··· 88 101 if ($app) { 89 102 if ($request->isFormPost()) { 90 103 $pinned = array_diff($pinned, array($unpin)); 91 - $preferences->setPreference( 92 - PhabricatorUserPreferences::PREFERENCE_APP_PINNED, 93 - $pinned); 94 - $preferences->save(); 104 + 105 + $this->writePinnedApplications($preferences, $pinned); 95 106 96 107 return id(new AphrontRedirectResponse()) 97 108 ->setURI($this->getPanelURI()); 98 109 } 99 110 100 - $dialog = id(new AphrontDialogView()) 101 - ->setUser($user) 111 + return $this->newDialog() 102 112 ->setTitle(pht('Unpin Application')) 113 + ->addHiddenInput('unpin', $unpin) 103 114 ->appendParagraph( 104 115 pht( 105 116 'Unpin the %s application from your home page?', 106 117 phutil_tag('strong', array(), $app->getName()))) 107 118 ->addSubmitButton(pht('Unpin Application')) 108 - ->addCanceLButton($this->getPanelURI()); 109 - 110 - return id(new AphrontDialogResponse())->setDialog($dialog); 119 + ->addCancelButton($this->getPanelURI()); 111 120 } 112 121 } 113 122 114 123 $order = $request->getStrList('order'); 115 124 if ($order && $request->validateCSRF()) { 116 - $preferences->setPreference( 117 - PhabricatorUserPreferences::PREFERENCE_APP_PINNED, 118 - $order); 119 - $preferences->save(); 125 + $this->writePinnedApplications($preferences, $order); 120 126 121 127 return id(new AphrontRedirectResponse()) 122 128 ->setURI($this->getPanelURI()); ··· 125 131 $list_id = celerity_generate_unique_node_id(); 126 132 127 133 $list = id(new PHUIObjectItemListView()) 128 - ->setUser($user) 134 + ->setViewer($viewer) 129 135 ->setID($list_id); 130 136 131 137 Javelin::initBehavior( ··· 182 188 ->setText(pht('Pin Application')) 183 189 ->setHref($this->getPanelURI().'?add=true') 184 190 ->setWorkflow(true) 185 - ->setIcon('fa-thumb-tack')); 191 + ->setIcon('fa-thumb-tack')) 192 + ->addActionLink( 193 + id(new PHUIButtonView()) 194 + ->setTag('a') 195 + ->setText(pht('Reset to Defaults')) 196 + ->setHref($this->getPanelURI().'?reset=true') 197 + ->setWorkflow(true) 198 + ->setIcon('fa-recycle')); 186 199 187 200 $box = id(new PHUIObjectBoxView()) 188 201 ->setHeader($header) 189 202 ->setObjectList($list); 190 203 191 204 return $box; 205 + } 206 + 207 + private function writePinnedApplications( 208 + PhabricatorUserPreferences $preferences, 209 + $pinned) { 210 + 211 + $viewer = $this->getViewer(); 212 + $request = $this->getController()->getRequest(); 213 + $pinned_key = PhabricatorPinnedApplicationsSetting::SETTINGKEY; 214 + 215 + $editor = id(new PhabricatorUserPreferencesEditor()) 216 + ->setActor($viewer) 217 + ->setContentSourceFromRequest($request) 218 + ->setContinueOnNoEffect(true) 219 + ->setContinueOnMissingFields(true); 220 + 221 + $xactions = array(); 222 + $xactions[] = $preferences->newTransaction($pinned_key, $pinned); 223 + $editor->applyTransactions($preferences, $xactions); 192 224 } 193 225 194 226 }
+18
src/applications/settings/panel/PhabricatorSettingsPanel.php
··· 217 217 ->addString($this->getPanelName()); 218 218 } 219 219 220 + protected function loadTargetPreferences() { 221 + $viewer = $this->getViewer(); 222 + $user = $this->getUser(); 223 + 224 + $preferences = PhabricatorUserPreferences::loadUserPreferences($user); 225 + 226 + PhabricatorPolicyFilter::requireCapability( 227 + $viewer, 228 + $preferences, 229 + PhabricatorPolicyCapability::CAN_EDIT); 230 + 231 + return $preferences; 232 + } 233 + 234 + protected function newDialog() { 235 + return $this->getController()->newDialog(); 236 + } 237 + 220 238 }
+33
src/applications/settings/setting/PhabricatorPinnedApplicationsSetting.php
··· 1 + <?php 2 + 3 + final class PhabricatorPinnedApplicationsSetting 4 + extends PhabricatorInternalSetting { 5 + 6 + const SETTINGKEY = 'app-pinned'; 7 + 8 + public function getSettingName() { 9 + return pht('Pinned Applications'); 10 + } 11 + 12 + public function getSettingDefaultValue() { 13 + $viewer = $this->getViewer(); 14 + 15 + $applications = id(new PhabricatorApplicationQuery()) 16 + ->setViewer($viewer) 17 + ->withInstalled(true) 18 + ->withUnlisted(false) 19 + ->withLaunchable(true) 20 + ->execute(); 21 + 22 + $pinned = array(); 23 + foreach ($applications as $application) { 24 + if ($application->isPinnedByDefault($viewer)) { 25 + $pinned[] = get_class($application); 26 + } 27 + } 28 + 29 + return $pinned; 30 + } 31 + 32 + 33 + }
+12 -33
src/applications/settings/storage/PhabricatorUserPreferences.php
··· 73 73 return null; 74 74 } 75 75 76 - return $setting->getSettingDefaultValue(); 77 - } 76 + $setting = id(clone $setting) 77 + ->setViewer($this->getUser()); 78 78 79 - private static function getSettingObject($key) { 80 - $settings = PhabricatorSetting::getAllSettings(); 81 - return idx($settings, $key); 79 + return $setting->getSettingDefaultValue(); 82 80 } 83 81 84 - public function getPinnedApplications(array $apps, PhabricatorUser $viewer) { 85 - $pref_pinned = self::PREFERENCE_APP_PINNED; 86 - $pinned = $this->getPreference($pref_pinned); 87 - 88 - if ($pinned) { 89 - return $pinned; 82 + public function getSettingValue($key) { 83 + if (array_key_exists($key, $this->preferences)) { 84 + return $this->preferences[$key]; 90 85 } 91 86 92 - $pref_tiles = self::PREFERENCE_APP_TILES; 93 - $tiles = $this->getPreference($pref_tiles, array()); 94 - $full_tile = 'full'; 87 + // TODO: If this setting set inherits from another preference set, 88 + // we would look it up here. 95 89 96 - $large = array(); 97 - foreach ($apps as $app) { 98 - $show = $app->isPinnedByDefault($viewer); 99 - 100 - // TODO: This is legacy stuff, clean it up eventually. This approximately 101 - // retains the old "tiles" preference. 102 - if (isset($tiles[get_class($app)])) { 103 - $show = ($tiles[get_class($app)] == $full_tile); 104 - } 105 - 106 - if ($show) { 107 - $large[] = get_class($app); 108 - } 109 - } 110 - 111 - return $large; 90 + return $this->getDefaultValue($key); 112 91 } 113 92 114 - public static function filterMonospacedCSSRule($monospaced) { 115 - // Prevent the user from doing dangerous things. 116 - return preg_replace('([^a-z0-9 ,"./]+)i', '', $monospaced); 93 + private static function getSettingObject($key) { 94 + $settings = PhabricatorSetting::getAllSettings(); 95 + return idx($settings, $key); 117 96 } 118 97 119 98 public function attachUser(PhabricatorUser $user = null) {