diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php
index ceaed7a676..48e6ef848e 100644
--- a/src/__celerity_resource_map__.php
+++ b/src/__celerity_resource_map__.php
@@ -1026,7 +1026,7 @@ celerity_register_resource_map(array(
),
'phabricator-feed-css' =>
array(
- 'uri' => '/res/617811ab/rsrc/css/application/feed/feed.css',
+ 'uri' => '/res/32e5879b/rsrc/css/application/feed/feed.css',
'type' => 'css',
'requires' =>
array(
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
index 9dbea838e9..6f1284e26f 100644
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -338,14 +338,17 @@ phutil_register_library_map(array(
'PhabricatorEmailLoginController' => 'applications/auth/controller/email',
'PhabricatorEmailTokenController' => 'applications/auth/controller/emailtoken',
'PhabricatorEnv' => 'infrastructure/env',
+ 'PhabricatorFeedConstants' => 'applications/feed/constants/base',
'PhabricatorFeedController' => 'applications/feed/controller/base',
'PhabricatorFeedDAO' => 'applications/feed/storage/base',
'PhabricatorFeedQuery' => 'applications/feed/query',
'PhabricatorFeedStory' => 'applications/feed/story/base',
'PhabricatorFeedStoryData' => 'applications/feed/storage/story',
+ 'PhabricatorFeedStoryDifferential' => 'applications/feed/story/differential',
'PhabricatorFeedStoryPublisher' => 'applications/feed/publisher',
'PhabricatorFeedStoryReference' => 'applications/feed/storage/storyreference',
'PhabricatorFeedStoryStatus' => 'applications/feed/story/status',
+ 'PhabricatorFeedStoryTypeConstants' => 'applications/feed/constants/story',
'PhabricatorFeedStoryUnknown' => 'applications/feed/story/unknown',
'PhabricatorFeedStoryView' => 'applications/feed/view/story',
'PhabricatorFeedStreamController' => 'applications/feed/controller/stream',
@@ -857,8 +860,10 @@ phutil_register_library_map(array(
'PhabricatorFeedController' => 'PhabricatorController',
'PhabricatorFeedDAO' => 'PhabricatorLiskDAO',
'PhabricatorFeedStoryData' => 'PhabricatorFeedDAO',
+ 'PhabricatorFeedStoryDifferential' => 'PhabricatorFeedStory',
'PhabricatorFeedStoryReference' => 'PhabricatorFeedDAO',
'PhabricatorFeedStoryStatus' => 'PhabricatorFeedStory',
+ 'PhabricatorFeedStoryTypeConstants' => 'PhabricatorFeedConstants',
'PhabricatorFeedStoryUnknown' => 'PhabricatorFeedStory',
'PhabricatorFeedStoryView' => 'PhabricatorFeedView',
'PhabricatorFeedStreamController' => 'PhabricatorFeedController',
diff --git a/src/applications/differential/editor/comment/DifferentialCommentEditor.php b/src/applications/differential/editor/comment/DifferentialCommentEditor.php
index be49a064a0..1834b4c9ef 100644
--- a/src/applications/differential/editor/comment/DifferentialCommentEditor.php
+++ b/src/applications/differential/editor/comment/DifferentialCommentEditor.php
@@ -411,6 +411,20 @@ class DifferentialCommentEditor {
id(new PhabricatorTimelineEvent('difx', $event_data))
->recordEvent();
+ // TODO: Move to a daemon?
+ id(new PhabricatorFeedStoryPublisher())
+ ->setStoryType(PhabricatorFeedStoryTypeConstants::STORY_DIFFERENTIAL)
+ ->setStoryData($event_data)
+ ->setStoryTime(time())
+ ->setStoryAuthorPHID($this->actorPHID)
+ ->setRelatedPHIDs(
+ array(
+ $revision->getPHID(),
+ $this->actorPHID,
+ $revision->getAuthorPHID(),
+ ))
+ ->publish();
+
// TODO: Move to a daemon?
PhabricatorSearchDifferentialIndexer::indexRevision($revision);
diff --git a/src/applications/differential/editor/comment/__init__.php b/src/applications/differential/editor/comment/__init__.php
index 74deebcb49..6dcae1bae7 100644
--- a/src/applications/differential/editor/comment/__init__.php
+++ b/src/applications/differential/editor/comment/__init__.php
@@ -14,6 +14,8 @@ phutil_require_module('phabricator', 'applications/differential/parser/markup');
phutil_require_module('phabricator', 'applications/differential/storage/changeset');
phutil_require_module('phabricator', 'applications/differential/storage/comment');
phutil_require_module('phabricator', 'applications/differential/storage/inlinecomment');
+phutil_require_module('phabricator', 'applications/feed/constants/story');
+phutil_require_module('phabricator', 'applications/feed/publisher');
phutil_require_module('phabricator', 'applications/herald/storage/transcript/base');
phutil_require_module('phabricator', 'applications/phid/handle/data');
phutil_require_module('phabricator', 'applications/search/index/indexer/differential');
diff --git a/src/applications/differential/editor/revision/DifferentialRevisionEditor.php b/src/applications/differential/editor/revision/DifferentialRevisionEditor.php
index 9b9e5b554c..a669d5fe69 100644
--- a/src/applications/differential/editor/revision/DifferentialRevisionEditor.php
+++ b/src/applications/differential/editor/revision/DifferentialRevisionEditor.php
@@ -375,6 +375,18 @@ class DifferentialRevisionEditor {
id(new PhabricatorTimelineEvent('difx', $event_data))
->recordEvent();
+ id(new PhabricatorFeedStoryPublisher())
+ ->setStoryType(PhabricatorFeedStoryTypeConstants::STORY_DIFFERENTIAL)
+ ->setStoryData($event_data)
+ ->setStoryTime(time())
+ ->setStoryAuthorPHID($revision->getAuthorPHID())
+ ->setRelatedPHIDs(
+ array(
+ $revision->getPHID(),
+ $revision->getAuthorPHID(),
+ ))
+ ->publish();
+
// TODO
// $revision->saveTransaction();
diff --git a/src/applications/differential/editor/revision/__init__.php b/src/applications/differential/editor/revision/__init__.php
index 7cb47b118b..038d9759d3 100644
--- a/src/applications/differential/editor/revision/__init__.php
+++ b/src/applications/differential/editor/revision/__init__.php
@@ -12,6 +12,8 @@ phutil_require_module('phabricator', 'applications/differential/mail/ccwelcome')
phutil_require_module('phabricator', 'applications/differential/mail/newdiff');
phutil_require_module('phabricator', 'applications/differential/storage/comment');
phutil_require_module('phabricator', 'applications/differential/storage/revision');
+phutil_require_module('phabricator', 'applications/feed/constants/story');
+phutil_require_module('phabricator', 'applications/feed/publisher');
phutil_require_module('phabricator', 'applications/herald/adapter/differential');
phutil_require_module('phabricator', 'applications/herald/engine/engine');
phutil_require_module('phabricator', 'applications/herald/storage/transcript/base');
diff --git a/src/applications/feed/constants/base/PhabricatorFeedConstants.php b/src/applications/feed/constants/base/PhabricatorFeedConstants.php
new file mode 100644
index 0000000000..79f1eab938
--- /dev/null
+++ b/src/applications/feed/constants/base/PhabricatorFeedConstants.php
@@ -0,0 +1,21 @@
+isFormPost()) {
$story = id(new PhabricatorFeedStoryPublisher())
->setRelatedPHIDs(array($viewer->getPHID()))
- ->setStoryType('PhabricatorFeedStoryStatus')
+ ->setStoryType(PhabricatorFeedStoryTypeConstants::STORY_STATUS)
->setStoryTime(time())
->setStoryAuthorPHID($viewer->getPHID())
->setStoryData(
diff --git a/src/applications/feed/controller/stream/__init__.php b/src/applications/feed/controller/stream/__init__.php
index 612ba97fbc..78489305b4 100644
--- a/src/applications/feed/controller/stream/__init__.php
+++ b/src/applications/feed/controller/stream/__init__.php
@@ -7,6 +7,7 @@
phutil_require_module('phabricator', 'aphront/response/redirect');
+phutil_require_module('phabricator', 'applications/feed/constants/story');
phutil_require_module('phabricator', 'applications/feed/controller/base');
phutil_require_module('phabricator', 'applications/feed/publisher');
phutil_require_module('phabricator', 'applications/feed/query');
diff --git a/src/applications/feed/publisher/PhabricatorFeedStoryPublisher.php b/src/applications/feed/publisher/PhabricatorFeedStoryPublisher.php
index a5c206209c..6f5d541ed6 100644
--- a/src/applications/feed/publisher/PhabricatorFeedStoryPublisher.php
+++ b/src/applications/feed/publisher/PhabricatorFeedStoryPublisher.php
@@ -71,7 +71,7 @@ final class PhabricatorFeedStoryPublisher {
$sql = array();
$conn = $ref->establishConnection('w');
- foreach ($this->relatedPHIDs as $phid) {
+ foreach (array_unique($this->relatedPHIDs) as $phid) {
$sql[] = qsprintf(
$conn,
'(%s, %s)',
diff --git a/src/applications/feed/story/differential/PhabricatorFeedStoryDifferential.php b/src/applications/feed/story/differential/PhabricatorFeedStoryDifferential.php
new file mode 100644
index 0000000000..83395108ad
--- /dev/null
+++ b/src/applications/feed/story/differential/PhabricatorFeedStoryDifferential.php
@@ -0,0 +1,86 @@
+getStoryData();
+ return array(
+ $this->getStoryData()->getAuthorPHID(),
+ $data->getValue('revision_phid'),
+ $data->getValue('revision_author_phid'),
+ );
+ }
+
+ public function getRequiredObjectPHIDs() {
+ return array(
+ $this->getStoryData()->getAuthorPHID(),
+ );
+ }
+
+ public function renderView() {
+ $data = $this->getStoryData();
+
+ $handles = $this->getHandles();
+ $author_phid = $data->getAuthorPHID();
+
+ $objects = $this->getObjects();
+
+ $view = new PhabricatorFeedStoryView();
+
+ $revision_phid = $data->getValue('revision_phid');
+
+ $action = $data->getValue('action');
+ $verb = DifferentialAction::getActionPastTenseVerb($action);
+
+ $view->setTitle(
+ ''.$handles[$author_phid]->renderLink().''.
+ ' '.$verb.' '.
+ ''.$handles[$revision_phid]->renderLink().'.');
+ $view->setEpoch($data->getEpoch());
+
+ $action = $data->getValue('action');
+ switch ($action) {
+ case DifferentialAction::ACTION_CREATE:
+ case DifferentialAction::ACTION_COMMIT:
+ $full_size = true;
+ break;
+ default:
+ $full_size = false;
+ break;
+ }
+
+ if ($full_size) {
+ if (!empty($objects[$author_phid])) {
+ $image_phid = $objects[$author_phid]->getProfileImagePHID();
+ $image_uri = PhabricatorFileURI::getViewURIForPHID($image_phid);
+ $view->setImage($image_uri);
+ }
+
+ $content = phutil_escape_html($data->getValue('feedback_content'));
+ $content = str_replace("\n", '
', $content);
+
+ $view->appendChild($content);
+ } else {
+ $view->setOneLineStory(true);
+ }
+
+ return $view;
+ }
+
+}
diff --git a/src/applications/feed/story/differential/__init__.php b/src/applications/feed/story/differential/__init__.php
new file mode 100644
index 0000000000..93cc715499
--- /dev/null
+++ b/src/applications/feed/story/differential/__init__.php
@@ -0,0 +1,17 @@
+viewer = $viewer;
return $this;
@@ -44,6 +46,11 @@ class PhabricatorFeedStoryView extends PhabricatorFeedView {
return $this;
}
+ public function setOneLineStory($one_line) {
+ $this->oneLine = $one_line;
+ return $this;
+ }
+
public function render() {
$head = phutil_render_tag(
@@ -53,29 +60,34 @@ class PhabricatorFeedStoryView extends PhabricatorFeedView {
),
nonempty($this->title, 'Untitled Story'));
- $body = phutil_render_tag(
- 'div',
- array(
- 'class' => 'phabricator-feed-story-body',
- ),
- $this->renderChildren());
-
- if ($this->epoch) {
- $foot = phabricator_datetime($this->epoch, $this->viewer);
- } else {
- $foot = '';
- }
-
- $foot = phutil_render_tag(
- 'div',
- array(
- 'class' => 'phabricator-feed-story-foot',
- ),
- $foot);
-
+ $body = null;
+ $foot = null;
$image_style = null;
- if ($this->image) {
- $image_style = 'background-image: url('.$this->image.')';
+
+ if (!$this->oneLine) {
+ $body = phutil_render_tag(
+ 'div',
+ array(
+ 'class' => 'phabricator-feed-story-body',
+ ),
+ $this->renderChildren());
+
+ if ($this->epoch) {
+ $foot = phabricator_datetime($this->epoch, $this->viewer);
+ } else {
+ $foot = '';
+ }
+
+ $foot = phutil_render_tag(
+ 'div',
+ array(
+ 'class' => 'phabricator-feed-story-foot',
+ ),
+ $foot);
+
+ if ($this->image) {
+ $image_style = 'background-image: url('.$this->image.')';
+ }
}
require_celerity_resource('phabricator-feed-css');
@@ -83,7 +95,9 @@ class PhabricatorFeedStoryView extends PhabricatorFeedView {
return phutil_render_tag(
'div',
array(
- 'class' => 'phabricator-feed-story',
+ 'class' => $this->oneLine
+ ? 'phabricator-feed-story phabricator-feed-story-one-line'
+ : 'phabricator-feed-story',
'style' => $image_style,
),
$head.$body.$foot);
diff --git a/webroot/rsrc/css/application/feed/feed.css b/webroot/rsrc/css/application/feed/feed.css
index 2ad5dfad84..089357f802 100644
--- a/webroot/rsrc/css/application/feed/feed.css
+++ b/webroot/rsrc/css/application/feed/feed.css
@@ -6,6 +6,13 @@
padding-left: 64px;
margin: .5em 0 1em;
background: 5px 2px no-repeat;
+ min-height: 64px;
+}
+
+.phabricator-feed-story-one-line {
+ min-height: 0;
+ font-size: 11px;
+ color: #444444;
}
.phabricator-feed-story-head {