mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-28 16:30:59 +01:00
Improve UI for selecting profile pictures
Summary: Ref T1703. Move profile pictures to a separate, dedicated interface. Instead of the 35 controls we currently provide, just show all the possible images we can find and then let the user upload an additional one if they want. Possible improvements to this interface: - Write an edge so we can show old profile pictures too. - The cropping/scaling got a bit buggy at some point, fix that. - Refresh OAuth sources which we're capable of refreshing before showing images (more work than I really want to deal with). - We could show little inset icons for the image source ("f" for Facebook, etc.) instead of just the tooltips. Test Plan: Chose images, uploaded new images, hit various error cases. {F49344} Reviewers: chad, btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T2919, T1703 Differential Revision: https://secure.phabricator.com/D6398
This commit is contained in:
parent
62ab1dcc62
commit
37b13ef2c9
8 changed files with 373 additions and 137 deletions
|
@ -3009,6 +3009,15 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/js/application/herald/PathTypeahead.js',
|
||||
),
|
||||
'people-profile-css' =>
|
||||
array(
|
||||
'uri' => '/res/1f0e94c5/rsrc/css/application/people/people-profile.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/application/people/people-profile.css',
|
||||
),
|
||||
'phabricator-action-header-view-css' =>
|
||||
array(
|
||||
'uri' => '/res/3b701648/rsrc/css/layout/phabricator-action-header-view.css',
|
||||
|
@ -3197,7 +3206,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'phabricator-header-view-css' =>
|
||||
array(
|
||||
'uri' => '/res/76173bb6/rsrc/css/layout/phabricator-header-view.css',
|
||||
'uri' => '/res/da35cfa0/rsrc/css/layout/phabricator-header-view.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -4140,7 +4149,7 @@ celerity_register_resource_map(array(
|
|||
), array(
|
||||
'packages' =>
|
||||
array(
|
||||
'd7254b92' =>
|
||||
'680ace9b' =>
|
||||
array(
|
||||
'name' => 'core.pkg.css',
|
||||
'symbols' =>
|
||||
|
@ -4188,7 +4197,7 @@ celerity_register_resource_map(array(
|
|||
40 => 'phabricator-property-list-view-css',
|
||||
41 => 'phabricator-tag-view-css',
|
||||
),
|
||||
'uri' => '/res/pkg/d7254b92/core.pkg.css',
|
||||
'uri' => '/res/pkg/680ace9b/core.pkg.css',
|
||||
'type' => 'css',
|
||||
),
|
||||
'75ccea43' =>
|
||||
|
@ -4382,16 +4391,16 @@ celerity_register_resource_map(array(
|
|||
'reverse' =>
|
||||
array(
|
||||
'aphront-attached-file-view-css' => 'adc3c36d',
|
||||
'aphront-dialog-view-css' => 'd7254b92',
|
||||
'aphront-error-view-css' => 'd7254b92',
|
||||
'aphront-form-view-css' => 'd7254b92',
|
||||
'aphront-list-filter-view-css' => 'd7254b92',
|
||||
'aphront-pager-view-css' => 'd7254b92',
|
||||
'aphront-panel-view-css' => 'd7254b92',
|
||||
'aphront-table-view-css' => 'd7254b92',
|
||||
'aphront-tokenizer-control-css' => 'd7254b92',
|
||||
'aphront-tooltip-css' => 'd7254b92',
|
||||
'aphront-typeahead-control-css' => 'd7254b92',
|
||||
'aphront-dialog-view-css' => '680ace9b',
|
||||
'aphront-error-view-css' => '680ace9b',
|
||||
'aphront-form-view-css' => '680ace9b',
|
||||
'aphront-list-filter-view-css' => '680ace9b',
|
||||
'aphront-pager-view-css' => '680ace9b',
|
||||
'aphront-panel-view-css' => '680ace9b',
|
||||
'aphront-table-view-css' => '680ace9b',
|
||||
'aphront-tokenizer-control-css' => '680ace9b',
|
||||
'aphront-tooltip-css' => '680ace9b',
|
||||
'aphront-typeahead-control-css' => '680ace9b',
|
||||
'differential-changeset-view-css' => 'dd27a69b',
|
||||
'differential-core-view-css' => 'dd27a69b',
|
||||
'differential-inline-comment-editor' => '4ad86dee',
|
||||
|
@ -4405,7 +4414,7 @@ celerity_register_resource_map(array(
|
|||
'differential-table-of-contents-css' => 'dd27a69b',
|
||||
'diffusion-commit-view-css' => 'c8ce2d88',
|
||||
'diffusion-icons-css' => 'c8ce2d88',
|
||||
'global-drag-and-drop-css' => 'd7254b92',
|
||||
'global-drag-and-drop-css' => '680ace9b',
|
||||
'inline-comment-summary-css' => 'dd27a69b',
|
||||
'javelin-aphlict' => '75ccea43',
|
||||
'javelin-behavior' => 'a9f14d76',
|
||||
|
@ -4479,55 +4488,55 @@ celerity_register_resource_map(array(
|
|||
'javelin-util' => 'a9f14d76',
|
||||
'javelin-vector' => 'a9f14d76',
|
||||
'javelin-workflow' => 'a9f14d76',
|
||||
'lightbox-attachment-css' => 'd7254b92',
|
||||
'lightbox-attachment-css' => '680ace9b',
|
||||
'maniphest-task-summary-css' => 'adc3c36d',
|
||||
'maniphest-transaction-detail-css' => 'adc3c36d',
|
||||
'phabricator-action-list-view-css' => 'd7254b92',
|
||||
'phabricator-application-launch-view-css' => 'd7254b92',
|
||||
'phabricator-action-list-view-css' => '680ace9b',
|
||||
'phabricator-application-launch-view-css' => '680ace9b',
|
||||
'phabricator-busy' => '75ccea43',
|
||||
'phabricator-content-source-view-css' => 'dd27a69b',
|
||||
'phabricator-core-css' => 'd7254b92',
|
||||
'phabricator-crumbs-view-css' => 'd7254b92',
|
||||
'phabricator-core-css' => '680ace9b',
|
||||
'phabricator-crumbs-view-css' => '680ace9b',
|
||||
'phabricator-drag-and-drop-file-upload' => '4ad86dee',
|
||||
'phabricator-dropdown-menu' => '75ccea43',
|
||||
'phabricator-file-upload' => '75ccea43',
|
||||
'phabricator-filetree-view-css' => 'd7254b92',
|
||||
'phabricator-flag-css' => 'd7254b92',
|
||||
'phabricator-form-view-css' => 'd7254b92',
|
||||
'phabricator-header-view-css' => 'd7254b92',
|
||||
'phabricator-filetree-view-css' => '680ace9b',
|
||||
'phabricator-flag-css' => '680ace9b',
|
||||
'phabricator-form-view-css' => '680ace9b',
|
||||
'phabricator-header-view-css' => '680ace9b',
|
||||
'phabricator-hovercard' => '75ccea43',
|
||||
'phabricator-jump-nav' => 'd7254b92',
|
||||
'phabricator-jump-nav' => '680ace9b',
|
||||
'phabricator-keyboard-shortcut' => '75ccea43',
|
||||
'phabricator-keyboard-shortcut-manager' => '75ccea43',
|
||||
'phabricator-main-menu-view' => 'd7254b92',
|
||||
'phabricator-main-menu-view' => '680ace9b',
|
||||
'phabricator-menu-item' => '75ccea43',
|
||||
'phabricator-nav-view-css' => 'd7254b92',
|
||||
'phabricator-nav-view-css' => '680ace9b',
|
||||
'phabricator-notification' => '75ccea43',
|
||||
'phabricator-notification-css' => 'd7254b92',
|
||||
'phabricator-notification-menu-css' => 'd7254b92',
|
||||
'phabricator-object-item-list-view-css' => 'd7254b92',
|
||||
'phabricator-notification-css' => '680ace9b',
|
||||
'phabricator-notification-menu-css' => '680ace9b',
|
||||
'phabricator-object-item-list-view-css' => '680ace9b',
|
||||
'phabricator-object-selector-css' => 'dd27a69b',
|
||||
'phabricator-phtize' => '75ccea43',
|
||||
'phabricator-prefab' => '75ccea43',
|
||||
'phabricator-project-tag-css' => 'adc3c36d',
|
||||
'phabricator-property-list-view-css' => 'd7254b92',
|
||||
'phabricator-remarkup-css' => 'd7254b92',
|
||||
'phabricator-property-list-view-css' => '680ace9b',
|
||||
'phabricator-remarkup-css' => '680ace9b',
|
||||
'phabricator-shaped-request' => '4ad86dee',
|
||||
'phabricator-side-menu-view-css' => 'd7254b92',
|
||||
'phabricator-standard-page-view' => 'd7254b92',
|
||||
'phabricator-tag-view-css' => 'd7254b92',
|
||||
'phabricator-side-menu-view-css' => '680ace9b',
|
||||
'phabricator-standard-page-view' => '680ace9b',
|
||||
'phabricator-tag-view-css' => '680ace9b',
|
||||
'phabricator-textareautils' => '75ccea43',
|
||||
'phabricator-tooltip' => '75ccea43',
|
||||
'phabricator-transaction-view-css' => 'd7254b92',
|
||||
'phabricator-zindex-css' => 'd7254b92',
|
||||
'phui-button-css' => 'd7254b92',
|
||||
'phui-form-css' => 'd7254b92',
|
||||
'phui-icon-view-css' => 'd7254b92',
|
||||
'phui-spacing-css' => 'd7254b92',
|
||||
'sprite-apps-large-css' => 'd7254b92',
|
||||
'sprite-gradient-css' => 'd7254b92',
|
||||
'sprite-icons-css' => 'd7254b92',
|
||||
'sprite-menu-css' => 'd7254b92',
|
||||
'syntax-highlighting-css' => 'd7254b92',
|
||||
'phabricator-transaction-view-css' => '680ace9b',
|
||||
'phabricator-zindex-css' => '680ace9b',
|
||||
'phui-button-css' => '680ace9b',
|
||||
'phui-form-css' => '680ace9b',
|
||||
'phui-icon-view-css' => '680ace9b',
|
||||
'phui-spacing-css' => '680ace9b',
|
||||
'sprite-apps-large-css' => '680ace9b',
|
||||
'sprite-gradient-css' => '680ace9b',
|
||||
'sprite-icons-css' => '680ace9b',
|
||||
'sprite-menu-css' => '680ace9b',
|
||||
'syntax-highlighting-css' => '680ace9b',
|
||||
),
|
||||
));
|
||||
|
|
|
@ -1344,6 +1344,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPeopleLogsController' => 'applications/people/controller/PhabricatorPeopleLogsController.php',
|
||||
'PhabricatorPeopleProfileController' => 'applications/people/controller/PhabricatorPeopleProfileController.php',
|
||||
'PhabricatorPeopleProfileEditController' => 'applications/people/controller/PhabricatorPeopleProfileEditController.php',
|
||||
'PhabricatorPeopleProfilePictureController' => 'applications/people/controller/PhabricatorPeopleProfilePictureController.php',
|
||||
'PhabricatorPeopleQuery' => 'applications/people/query/PhabricatorPeopleQuery.php',
|
||||
'PhabricatorPeopleSearchEngine' => 'applications/people/query/PhabricatorPeopleSearchEngine.php',
|
||||
'PhabricatorPeopleTestDataGenerator' => 'applications/people/lipsum/PhabricatorPeopleTestDataGenerator.php',
|
||||
|
@ -3303,6 +3304,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleProfileController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleProfileEditController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleProfilePictureController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhabricatorPeopleSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
'PhabricatorPeopleTestDataGenerator' => 'PhabricatorTestDataGenerator',
|
||||
|
|
|
@ -94,7 +94,6 @@ final class PhabricatorImageTransformer {
|
|||
}
|
||||
|
||||
$cropped = $this->applyScaleWithImagemagick($file, $x, $scaled_y);
|
||||
|
||||
if ($cropped != null) {
|
||||
return $cropped;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,8 @@ final class PhabricatorApplicationPeople extends PhabricatorApplication {
|
|||
'ldap/' => 'PhabricatorPeopleLdapController',
|
||||
'editprofile/(?P<id>[1-9]\d*)/' =>
|
||||
'PhabricatorPeopleProfileEditController',
|
||||
'picture/(?P<id>[1-9]\d*)/' =>
|
||||
'PhabricatorPeopleProfilePictureController',
|
||||
),
|
||||
'/p/(?P<username>[\w._-]+)/(?:(?P<page>\w+)/)?'
|
||||
=> 'PhabricatorPeopleProfileController',
|
||||
|
|
|
@ -117,6 +117,14 @@ final class PhabricatorPeopleProfileController
|
|||
->setDisabled(!$can_edit)
|
||||
->setWorkflow(!$can_edit));
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('image')
|
||||
->setName(pht('Edit Profile Picture'))
|
||||
->setHref($this->getApplicationURI('picture/'.$user->getID().'/'))
|
||||
->setDisabled(!$can_edit)
|
||||
->setWorkflow(!$can_edit));
|
||||
|
||||
if ($viewer->getIsAdmin()) {
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
|
|
|
@ -0,0 +1,292 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPeopleProfilePictureController
|
||||
extends PhabricatorPeopleController {
|
||||
|
||||
private $id;
|
||||
|
||||
public function shouldRequireAdmin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->id = $data['id'];
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$viewer = $request->getUser();
|
||||
|
||||
$user = id(new PhabricatorPeopleQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($this->id))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
if (!$user) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$profile_uri = '/p/'.$user->getUsername().'/';
|
||||
|
||||
$supported_formats = PhabricatorFile::getTransformableImageFormats();
|
||||
$e_file = true;
|
||||
$errors = array();
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
$phid = $request->getStr('phid');
|
||||
$is_default = false;
|
||||
if ($phid == PhabricatorPHIDConstants::PHID_VOID) {
|
||||
$phid = null;
|
||||
$is_default = true;
|
||||
} else if ($phid) {
|
||||
$file = id(new PhabricatorFileQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs(array($phid))
|
||||
->executeOne();
|
||||
} else {
|
||||
if ($request->getFileExists('picture')) {
|
||||
$file = PhabricatorFile::newFromPHPUpload(
|
||||
$_FILES['picture'],
|
||||
array(
|
||||
'authorPHID' => $viewer->getPHID(),
|
||||
));
|
||||
} else {
|
||||
$e_file = pht('Required');
|
||||
$errors[] = pht(
|
||||
'You must choose a file when uploading a new profile picture.');
|
||||
}
|
||||
}
|
||||
|
||||
if (!$errors && !$is_default) {
|
||||
if (!$file->isTransformableImage()) {
|
||||
$e_file = pht('Not Supported');
|
||||
$errors[] = pht(
|
||||
'This server only supports these image formats: %s.',
|
||||
implode(', ', $supported_formats));
|
||||
} else {
|
||||
$xformer = new PhabricatorImageTransformer();
|
||||
$xformed = $xformer->executeProfileTransform(
|
||||
$file,
|
||||
$width = 50,
|
||||
$min_height = 50,
|
||||
$max_height = 50);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$errors) {
|
||||
$user->setProfileImagePHID($xformed->getPHID());
|
||||
$user->save();
|
||||
return id(new AphrontRedirectResponse())->setURI($profile_uri);
|
||||
}
|
||||
}
|
||||
|
||||
$title = pht('Edit Profile Picture');
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addCrumb(
|
||||
id(new PhabricatorCrumbView())
|
||||
->setName($user->getUsername())
|
||||
->setHref($profile_uri));
|
||||
$crumbs->addCrumb(
|
||||
id(new PhabricatorCrumbView())
|
||||
->setName($title));
|
||||
|
||||
$form = id(new AphrontFormLayoutView())
|
||||
->setUser($viewer);
|
||||
|
||||
$default_image = PhabricatorFile::loadBuiltin($viewer, 'profile.png');
|
||||
|
||||
$images = array();
|
||||
|
||||
$current = $user->getProfileImagePHID();
|
||||
if ($current) {
|
||||
$files = id(new PhabricatorFileQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs(array($current))
|
||||
->execute();
|
||||
if ($files) {
|
||||
$file = head($files);
|
||||
if ($file->isTransformableImage()) {
|
||||
$images[$current] = array(
|
||||
'uri' => $file->getBestURI(),
|
||||
'tip' => pht('Current Picture'),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try to add external account images for any associated external accounts.
|
||||
$accounts = id(new PhabricatorExternalAccountQuery())
|
||||
->setViewer($viewer)
|
||||
->withUserPHIDs(array($user->getPHID()))
|
||||
->needImages(true)
|
||||
->execute();
|
||||
|
||||
foreach ($accounts as $account) {
|
||||
$file = $account->getProfileImageFile();
|
||||
if ($account->getProfileImagePHID() != $file->getPHID()) {
|
||||
// This is a default image, just skip it.
|
||||
continue;
|
||||
}
|
||||
|
||||
$provider = PhabricatorAuthProvider::getEnabledProviderByKey(
|
||||
$account->getProviderKey());
|
||||
if ($provider) {
|
||||
$tip = pht('Picture From %s', $provider->getProviderName());
|
||||
} else {
|
||||
$tip = pht('Picture From External Account');
|
||||
}
|
||||
|
||||
if ($file->isTransformableImage()) {
|
||||
$images[$file->getPHID()] = array(
|
||||
'uri' => $file->getBestURI(),
|
||||
'tip' => $tip,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Try to add Gravatar images for any email addresses associated with the
|
||||
// account.
|
||||
if (PhabricatorEnv::getEnvConfig('security.allow-outbound-http')) {
|
||||
$emails = id(new PhabricatorUserEmail())->loadAllWhere(
|
||||
'userPHID = %s ORDER BY address',
|
||||
$viewer->getPHID());
|
||||
|
||||
$futures = array();
|
||||
foreach ($emails as $email_object) {
|
||||
$email = $email_object->getAddress();
|
||||
|
||||
$hash = md5(strtolower(trim($email)));
|
||||
$uri = id(new PhutilURI("https://secure.gravatar.com/avatar/{$hash}"))
|
||||
->setQueryParams(
|
||||
array(
|
||||
'size' => 200,
|
||||
'default' => '404',
|
||||
'rating' => 'x',
|
||||
));
|
||||
$futures[$email] = new HTTPSFuture($uri);
|
||||
}
|
||||
|
||||
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
||||
foreach (Futures($futures) as $email => $future) {
|
||||
try {
|
||||
list($body) = $future->resolvex();
|
||||
$file = PhabricatorFile::newFromFileData(
|
||||
$body,
|
||||
array(
|
||||
'name' => 'profile-gravatar',
|
||||
'ttl' => (60 * 60 * 4),
|
||||
));
|
||||
if ($file->isTransformableImage()) {
|
||||
$images[$file->getPHID()] = array(
|
||||
'uri' => $file->getBestURI(),
|
||||
'tip' => pht('Gravatar for %s', $email),
|
||||
);
|
||||
}
|
||||
} catch (Exception $ex) {
|
||||
// Just continue.
|
||||
}
|
||||
}
|
||||
unset($unguarded);
|
||||
}
|
||||
|
||||
$images[PhabricatorPHIDConstants::PHID_VOID] = array(
|
||||
'uri' => $default_image->getBestURI(),
|
||||
'tip' => pht('Default Picture'),
|
||||
);
|
||||
|
||||
require_celerity_resource('people-profile-css');
|
||||
Javelin::initBehavior('phabricator-tooltips', array());
|
||||
|
||||
$buttons = array();
|
||||
foreach ($images as $phid => $spec) {
|
||||
$button = javelin_tag(
|
||||
'button',
|
||||
array(
|
||||
'class' => 'grey profile-image-button',
|
||||
'sigil' => 'has-tooltip',
|
||||
'meta' => array(
|
||||
'tip' => $spec['tip'],
|
||||
'size' => 300,
|
||||
),
|
||||
),
|
||||
phutil_tag(
|
||||
'img',
|
||||
array(
|
||||
'height' => 50,
|
||||
'width' => 50,
|
||||
'src' => $spec['uri'],
|
||||
)));
|
||||
|
||||
$button = array(
|
||||
phutil_tag(
|
||||
'input',
|
||||
array(
|
||||
'type' => 'hidden',
|
||||
'name' => 'phid',
|
||||
'value' => $phid,
|
||||
)),
|
||||
$button);
|
||||
|
||||
$button = phabricator_form(
|
||||
$viewer,
|
||||
array(
|
||||
'class' => 'profile-image-form',
|
||||
'method' => 'POST',
|
||||
),
|
||||
$button);
|
||||
|
||||
$buttons[] = $button;
|
||||
}
|
||||
|
||||
$form->appendChild(
|
||||
id(new AphrontFormMarkupControl())
|
||||
->setLabel(pht('Current Picture'))
|
||||
->setValue(array_slice($buttons, 0, 1)));
|
||||
|
||||
$form->appendChild(
|
||||
id(new AphrontFormMarkupControl())
|
||||
->setLabel(pht('Use Picture'))
|
||||
->setValue(array_slice($buttons, 1)));
|
||||
|
||||
$upload_head = id(new PhabricatorHeaderView())
|
||||
->setHeader(pht('Upload New Picture'));
|
||||
|
||||
$upload_form = id(new AphrontFormView())
|
||||
->setUser($user)
|
||||
->setFlexible(true)
|
||||
->setEncType('multipart/form-data')
|
||||
->appendChild(
|
||||
id(new AphrontFormFileControl())
|
||||
->setName('picture')
|
||||
->setLabel(pht('Upload Picture'))
|
||||
->setError($e_file)
|
||||
->setCaption(
|
||||
pht('Supported formats: %s', implode(', ', $supported_formats))))
|
||||
->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->addCancelButton($profile_uri)
|
||||
->setValue(pht('Upload Picture')));
|
||||
|
||||
if ($errors) {
|
||||
$errors = id(new AphrontErrorView())->setErrors($errors);
|
||||
}
|
||||
|
||||
return $this->buildApplicationPage(
|
||||
array(
|
||||
$crumbs,
|
||||
$errors,
|
||||
$form,
|
||||
$upload_head,
|
||||
$upload_form,
|
||||
),
|
||||
array(
|
||||
'title' => $title,
|
||||
'device' => true,
|
||||
'dust' => true,
|
||||
));
|
||||
}
|
||||
}
|
|
@ -18,11 +18,6 @@ final class PhabricatorSettingsPanelProfile
|
|||
public function processRequest(AphrontRequest $request) {
|
||||
$user = $request->getUser();
|
||||
|
||||
$profile = $user->loadUserProfile();
|
||||
|
||||
$supported_formats = PhabricatorFile::getTransformableImageFormats();
|
||||
|
||||
$e_image = null;
|
||||
$errors = array();
|
||||
if ($request->isFormPost()) {
|
||||
$sex = $request->getStr('sex');
|
||||
|
@ -36,64 +31,8 @@ final class PhabricatorSettingsPanelProfile
|
|||
// Checked in runtime.
|
||||
$user->setTranslation($request->getStr('translation'));
|
||||
|
||||
$default_image = $request->getExists('default_image');
|
||||
$gravatar_email = $request->getStr('gravatar');
|
||||
if ($default_image) {
|
||||
$profile->setProfileImagePHID(null);
|
||||
$user->setProfileImagePHID(null);
|
||||
} else if (!empty($gravatar_email) || $request->getFileExists('image')) {
|
||||
$file = null;
|
||||
if (!empty($gravatar_email)) {
|
||||
// These steps recommended by:
|
||||
// https://en.gravatar.com/site/implement/hash/
|
||||
$trimmed = trim($gravatar_email);
|
||||
$lower_cased = strtolower($trimmed);
|
||||
$hash = md5($lower_cased);
|
||||
$url = 'http://www.gravatar.com/avatar/'.($hash).'?s=200';
|
||||
$file = PhabricatorFile::newFromFileDownload(
|
||||
$url,
|
||||
array(
|
||||
'name' => 'gravatar',
|
||||
'authorPHID' => $user->getPHID(),
|
||||
));
|
||||
} else if ($request->getFileExists('image')) {
|
||||
$file = PhabricatorFile::newFromPHPUpload(
|
||||
$_FILES['image'],
|
||||
array(
|
||||
'authorPHID' => $user->getPHID(),
|
||||
));
|
||||
}
|
||||
|
||||
$okay = $file->isTransformableImage();
|
||||
if ($okay) {
|
||||
$xformer = new PhabricatorImageTransformer();
|
||||
|
||||
// Generate the large picture for the profile page.
|
||||
$large_xformed = $xformer->executeProfileTransform(
|
||||
$file,
|
||||
$width = 280,
|
||||
$min_height = 140,
|
||||
$max_height = 420);
|
||||
$profile->setProfileImagePHID($large_xformed->getPHID());
|
||||
|
||||
// Generate the small picture for comments, etc.
|
||||
$small_xformed = $xformer->executeProfileTransform(
|
||||
$file,
|
||||
$width = 50,
|
||||
$min_height = 50,
|
||||
$max_height = 50);
|
||||
$user->setProfileImagePHID($small_xformed->getPHID());
|
||||
} else {
|
||||
$e_image = pht('Not Supported');
|
||||
$errors[] =
|
||||
pht('This server only supports these image formats:').
|
||||
' ' .implode(', ', $supported_formats);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$errors) {
|
||||
$user->save();
|
||||
$profile->save();
|
||||
$response = id(new AphrontRedirectResponse())
|
||||
->setURI($this->getPanelURI('?saved=true'));
|
||||
return $response;
|
||||
|
@ -116,7 +55,6 @@ final class PhabricatorSettingsPanelProfile
|
|||
}
|
||||
}
|
||||
|
||||
$img_src = $user->loadProfileImageURI();
|
||||
$profile_uri = PhabricatorEnv::getURI('/p/'.$user->getUsername().'/');
|
||||
|
||||
$sexes = array(
|
||||
|
@ -144,7 +82,6 @@ final class PhabricatorSettingsPanelProfile
|
|||
$form = new AphrontFormView();
|
||||
$form
|
||||
->setUser($request->getUser())
|
||||
->setEncType('multipart/form-data')
|
||||
->appendChild(
|
||||
id(new AphrontFormSelectControl())
|
||||
->setOptions($sexes)
|
||||
|
@ -156,37 +93,11 @@ final class PhabricatorSettingsPanelProfile
|
|||
->setOptions($translations)
|
||||
->setLabel(pht('Translation'))
|
||||
->setName('translation')
|
||||
->setValue($user->getTranslation()))
|
||||
->appendChild(
|
||||
id(new AphrontFormMarkupControl())
|
||||
->setLabel(pht('Profile Image'))
|
||||
->setValue(
|
||||
phutil_tag(
|
||||
'img',
|
||||
array(
|
||||
'src' => $img_src,
|
||||
))))
|
||||
->appendChild(
|
||||
id(new AphrontFormImageControl())
|
||||
->setLabel(pht('Change Image'))
|
||||
->setName('image')
|
||||
->setError($e_image)
|
||||
->setCaption(
|
||||
pht('Supported formats: %s', implode(', ', $supported_formats))));
|
||||
|
||||
if (PhabricatorEnv::getEnvConfig('security.allow-outbound-http')) {
|
||||
$form->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
->setLabel(pht('Import Gravatar'))
|
||||
->setName('gravatar')
|
||||
->setError($e_image)
|
||||
->setCaption(pht('Enter gravatar email address')));
|
||||
}
|
||||
->setValue($user->getTranslation()));
|
||||
|
||||
$form->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->setValue(pht('Save'))
|
||||
->addCancelButton('/p/'.$user->getUsername().'/'));
|
||||
->setValue(pht('Save')));
|
||||
|
||||
$header = new PhabricatorHeaderView();
|
||||
$header->setHeader(pht('Edit Profile Details'));
|
||||
|
|
13
webroot/rsrc/css/application/people/people-profile.css
Normal file
13
webroot/rsrc/css/application/people/people-profile.css
Normal file
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* @provides people-profile-css
|
||||
*/
|
||||
|
||||
form.profile-image-form {
|
||||
display: inline-block;
|
||||
margin: 0 8px 8px 0;
|
||||
}
|
||||
|
||||
button.profile-image-button {
|
||||
padding: 4px;
|
||||
margin: 0;
|
||||
}
|
Loading…
Reference in a new issue