Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2892979
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Advanced/Developer...
View Handle
View Hovercard
Size
19 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/applications/conpherence/controller/ConpherenceController.php b/src/applications/conpherence/controller/ConpherenceController.php
index c697eb5af1..d3026bfec7 100644
--- a/src/applications/conpherence/controller/ConpherenceController.php
+++ b/src/applications/conpherence/controller/ConpherenceController.php
@@ -1,294 +1,293 @@
<?php
/**
* @group conpherence
*/
abstract class ConpherenceController extends PhabricatorController {
private $conpherences;
private $readConpherences;
private $unreadConpherences;
public function setUnreadConpherences(array $conpherences) {
assert_instances_of($conpherences, 'ConpherenceThread');
$this->unreadConpherences = $conpherences;
return $this;
}
public function getUnreadConpherences() {
return $this->unreadConpherences;
}
public function setReadConpherences(array $conpherences) {
assert_instances_of($conpherences, 'ConpherenceThread');
$this->readConpherences = $conpherences;
return $this;
}
public function getReadConpherences() {
return $this->readConpherences;
}
/**
* Try for a full set of unread conpherences, and if we fail
* load read conpherences. Additional conpherences in either category
* are loaded asynchronously.
*/
public function loadStartingConpherences($current_selection_epoch = null) {
$user = $this->getRequest()->getUser();
$read_participant_query = id(new ConpherenceParticipantQuery())
->withParticipantPHIDs(array($user->getPHID()));
$read_status = ConpherenceParticipationStatus::UP_TO_DATE;
if ($current_selection_epoch) {
$read_one = $read_participant_query
->withParticipationStatus($read_status)
->withDateTouched($current_selection_epoch, '>')
->execute();
$read_two = $read_participant_query
->withDateTouched($current_selection_epoch, '<=')
->execute();
$read = array_merge($read_one, $read_two);
} else {
$read = $read_participant_query
->withParticipationStatus($read_status)
->execute();
}
$unread_status = ConpherenceParticipationStatus::BEHIND;
$unread = id(new ConpherenceParticipantQuery())
->withParticipantPHIDs(array($user->getPHID()))
->withParticipationStatus($unread_status)
->execute();
$all_participation = $unread + $read;
$all_conpherence_phids = array_keys($all_participation);
$all_conpherences = id(new ConpherenceThreadQuery())
->setViewer($user)
->withPHIDs($all_conpherence_phids)
->execute();
$unread_conpherences = array_select_keys(
$all_conpherences,
array_keys($unread));
$this->setUnreadConpherences($unread_conpherences);
$read_conpherences = array_select_keys(
$all_conpherences,
array_keys($read));
$this->setReadConpherences($read_conpherences);
return $this;
}
public function buildSideNavView($filter = null, $for_application = false) {
require_celerity_resource('conpherence-menu-css');
$unread_conpherences = $this->getUnreadConpherences();
$read_conpherences = $this->getReadConpherences();
$user = $this->getRequest()->getUser();
$menu = new PhabricatorMenuView();
$nav = AphrontSideNavFilterView::newFromMenu($menu);
$nav->addClass('conpherence-menu');
$nav->setMenuID('conpherence-menu');
if (!$for_application) {
$nav->addMenuItem(
id(new PhabricatorMenuItemView())
->setName(pht('New Conversation'))
->setWorkflow(true)
->setKey('new')
->setHref($this->getApplicationURI('new/'))
->setType(PhabricatorMenuItemView::TYPE_BUTTON));
$nav->addLabel(pht('Unread'));
$nav = $this->addConpherencesToNav(
$unread_conpherences,
$nav,
false);
$nav->addLabel(pht('Read'));
$nav = $this->addConpherencesToNav(
$read_conpherences,
$nav,
true);
$nav->selectFilter($filter);
} else {
$nav->addFilter(
'new',
pht('New Conversation'),
$this->getApplicationURI('new/'));
}
return $nav;
}
private function addConpherencesToNav(
array $conpherences,
AphrontSideNavFilterView $nav,
$read = false) {
$user = $this->getRequest()->getUser();
foreach ($conpherences as $conpherence) {
$item = $this->buildConpherenceMenuItem($conpherence);
$nav->addCustomBlock($item->render());
}
if (empty($conpherences) || $read) {
$nav->addCustomBlock($this->getNoConpherencesBlock());
}
return $nav;
}
private function getNoConpherencesBlock() {
return phutil_tag(
'div',
array(
'class' => 'no-conpherences-menu-item'
),
pht('No more conpherences.'));
}
public function buildApplicationMenu() {
return $this->buildSideNavView(
$filter = null,
$for_application = true)->getMenu();
}
public function buildApplicationCrumbs() {
$crumbs = parent::buildApplicationCrumbs();
$crumbs
->addAction(
id(new PhabricatorMenuItemView())
->setName(pht('New Conversation'))
->setHref($this->getApplicationURI('new/'))
->setIcon('create'))
->addCrumb(
id(new PhabricatorCrumbView())
->setName(pht('Conpherence')));
return $crumbs;
}
protected function buildConpherenceMenuItem($conpherence) {
$user = $this->getRequest()->getUser();
$uri = $this->getApplicationURI('view/'.$conpherence->getID().'/');
$data = $conpherence->getDisplayData(
$user,
null);
$title = $data['title'];
$subtitle = $data['subtitle'];
$unread_count = $data['unread_count'];
$epoch = $data['epoch'];
$image = $data['image'];
$snippet = $data['snippet'];
$item = id(new ConpherenceMenuItemView())
->setUser($user)
->setTitle($title)
->setSubtitle($subtitle)
->setHref($uri)
->setEpoch($epoch)
->setImageURI($image)
->setMessageText($snippet)
->setUnreadCount($unread_count)
->setID($conpherence->getPHID().'-nav-item')
->addSigil('conpherence-menu-click')
->setMetadata(
array(
'id' => $conpherence->getID(),
- 'phid' => $conpherence->getPHID(),
));
return $item;
}
protected function buildHeaderPaneContent(ConpherenceThread $conpherence) {
$user = $this->getRequest()->getUser();
$display_data = $conpherence->getDisplayData(
$user,
ConpherenceImageData::SIZE_HEAD);
$edit_href = $this->getApplicationURI('update/'.$conpherence->getID().'/');
$class_mod = $display_data['image_class'];
$header =
phutil_tag(
'div',
array(
'class' => 'upload-photo'
),
pht('Drop photo here to change this Conpherence photo.')).
javelin_tag(
'a',
array(
'class' => 'edit',
'href' => $edit_href,
'sigil' => 'conpherence-edit-metadata',
'meta' => array(
'action' => 'metadata'
)
),
'').
phutil_tag(
'div',
array(
'class' => $class_mod.'header-image',
'style' => 'background-image: url('.$display_data['image'].');'
),
'').
phutil_tag(
'div',
array(
'class' => $class_mod.'title',
),
$display_data['title']).
phutil_tag(
'div',
array(
'class' => $class_mod.'subtitle',
),
$display_data['subtitle']);
return $header;
}
protected function renderConpherenceTransactions(
ConpherenceThread $conpherence) {
$user = $this->getRequest()->getUser();
$transactions = $conpherence->getTransactions();
$handles = $conpherence->getHandles();
$rendered_transactions = array();
$engine = id(new PhabricatorMarkupEngine())
->setViewer($user);
foreach ($transactions as $key => $transaction) {
if ($transaction->shouldHide()) {
unset($transactions[$key]);
continue;
}
if ($transaction->getComment()) {
$engine->addObject(
$transaction->getComment(),
PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT);
}
}
$engine->process();
foreach ($transactions as $transaction) {
$rendered_transactions[] = id(new ConpherenceTransactionView())
->setUser($user)
->setConpherenceTransaction($transaction)
->setHandles($handles)
->setMarkupEngine($engine)
->render();
}
$latest_transaction_id = $transaction->getID();
$rendered_transactions = phutil_implode_html(' ', $rendered_transactions);
return array(
'transactions' => $rendered_transactions,
'latest_transaction_id' => $latest_transaction_id
);
}
}
diff --git a/src/applications/conpherence/controller/ConpherenceListController.php b/src/applications/conpherence/controller/ConpherenceListController.php
index 7b9af17098..b138b676e1 100644
--- a/src/applications/conpherence/controller/ConpherenceListController.php
+++ b/src/applications/conpherence/controller/ConpherenceListController.php
@@ -1,69 +1,71 @@
<?php
/**
* @group conpherence
*/
final class ConpherenceListController extends
ConpherenceController {
private $conpherenceID;
public function setConpherenceID($conpherence_id) {
$this->conpherenceID = $conpherence_id;
return $this;
}
public function getConpherenceID() {
return $this->conpherenceID;
}
public function willProcessRequest(array $data) {
$this->setConpherenceID(idx($data, 'id'));
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$title = pht('Conpherence');
$conpherence_id = $this->getConpherenceID();
$current_selection_epoch = null;
- $selected_phid = null;
+ $conpherence = null;
if ($conpherence_id) {
$conpherence = id(new ConpherenceThreadQuery())
->setViewer($user)
->withIDs(array($conpherence_id))
->executeOne();
if (!$conpherence) {
return new Aphront404Response();
}
if ($conpherence->getTitle()) {
$title = $conpherence->getTitle();
}
- $selected_phid = $conpherence->getPHID();
$participant = $conpherence->getParticipant($user->getPHID());
$current_selection_epoch = $participant->getDateTouched();
}
$this->loadStartingConpherences($current_selection_epoch);
$nav = $this->buildSideNavView();
$main_pane = id(new ConpherenceLayoutView())
- ->setBaseURI($this->getApplicationURI())
- ->setSelectedConpherencePHID($selected_phid);
+ ->setBaseURI($this->getApplicationURI());
+
+ if ($conpherence) {
+ $main_pane->setThread($conpherence);
+ }
$nav->appendChild(
array(
$main_pane,
));
return $this->buildApplicationPage(
$nav,
array(
'title' => $title,
'device' => true,
));
}
}
diff --git a/src/applications/conpherence/view/ConpherenceLayoutView.php b/src/applications/conpherence/view/ConpherenceLayoutView.php
index cda4035d65..fdcc57a059 100644
--- a/src/applications/conpherence/view/ConpherenceLayoutView.php
+++ b/src/applications/conpherence/view/ConpherenceLayoutView.php
@@ -1,88 +1,87 @@
<?php
final class ConpherenceLayoutView extends AphrontView {
- private $selectedConpherencePHID;
+ private $thread;
private $baseURI;
public function setBaseURI($base_uri) {
$this->baseURI = $base_uri;
return $this;
}
- public function setSelectedConpherencePHID($selected_conpherence_phid) {
- $this->selectedConpherencePHID = $selected_conpherence_phid;
+ public function setThread(ConpherenceThread $thread) {
+ $this->thread = $thread;
return $this;
}
public function render() {
Javelin::initBehavior('conpherence-menu',
array(
'base_uri' => $this->baseURI,
'header' => 'conpherence-header-pane',
'messages' => 'conpherence-messages',
'messages_pane' => 'conpherence-message-pane',
'widgets_pane' => 'conpherence-widget-pane',
'form_pane' => 'conpherence-form',
'menu_pane' => 'conpherence-menu',
- 'selected_conpherence_id' => $this->selectedConpherencePHID,
- 'fancy_ajax' => (bool)$this->selectedConpherencePHID,
+ 'selectedID' => ($this->thread ? $this->thread->getID() : null),
));
Javelin::initBehavior('conpherence-drag-and-drop-photo',
array(
'target' => 'conpherence-header-pane',
'form_pane' => 'conpherence-form',
'upload_uri' => '/file/dropupload/',
'activated_class' => 'conpherence-header-upload-photo',
));
return javelin_tag(
'div',
array(
'id' => 'conpherence-main-pane',
'sigil' => 'conpherence-layout'
),
array(
javelin_tag(
'div',
array(
'class' => 'conpherence-header-pane',
'id' => 'conpherence-header-pane',
'sigil' => 'conpherence-header',
),
''),
phutil_tag(
'div',
array(
'class' => 'conpherence-widget-pane',
'id' => 'conpherence-widget-pane'
),
''),
javelin_tag(
'div',
array(
'class' => 'conpherence-message-pane',
'id' => 'conpherence-message-pane'
),
array(
javelin_tag(
'div',
array(
'class' => 'conpherence-messages',
'id' => 'conpherence-messages',
'sigil' => 'conpherence-messages',
),
''),
phutil_tag(
'div',
array(
'id' => 'conpherence-form'
),
'')
))
));
}
}
diff --git a/webroot/rsrc/js/application/conpherence/behavior-menu.js b/webroot/rsrc/js/application/conpherence/behavior-menu.js
index 2e00c65f8b..028a651bd2 100644
--- a/webroot/rsrc/js/application/conpherence/behavior-menu.js
+++ b/webroot/rsrc/js/application/conpherence/behavior-menu.js
@@ -1,169 +1,172 @@
-/**
+<</**
* @provides javelin-behavior-conpherence-menu
* @requires javelin-behavior
* javelin-dom
* javelin-request
* javelin-stratcom
* javelin-workflow
* javelin-behavior-device
*/
JX.behavior('conpherence-menu', function(config) {
var thread = {
selected: null,
node: null,
visible: null
};
+ function selectthreadid(id) {
+ var threads = JX.DOM.scry(document.body, 'a', 'conpherence-menu-click');
+ for (var ii = 0; ii < threads.length; ii++) {
+ var data = JX.Stratcom.getData(threads[ii]);
+ if (data.id == id) {
+ selectthread(threads[ii]);
+ return;
+ }
+ }
+ }
+
function selectthread(node) {
if (node === thread.node) {
return;
}
if (thread.node) {
JX.DOM.alterClass(thread.node, 'conpherence-selected', false);
JX.DOM.alterClass(thread.node, 'hide-unread-count', false);
}
JX.DOM.alterClass(node, 'conpherence-selected', true);
JX.DOM.alterClass(node, 'hide-unread-count', true);
thread.node = node;
var data = JX.Stratcom.getData(node);
- thread.selected = data.phid;
+ thread.selected = data.id;
- // TODO: These URIs don't work yet, so don't push them until they do.
- // JX.History.push(config.base_uri + 'view/' + data.id + '/');
+ JX.History.replace(config.base_uri + data.id + '/');
redrawthread();
}
function redrawthread() {
if (!thread.node) {
return;
}
if (thread.visible == thread.selected) {
return;
}
var data = JX.Stratcom.getData(thread.node);
var uri = config.base_uri + 'view/' + data.id + '/';
var widget_uri = config.base_uri + 'widget/' + data.id + '/';
new JX.Workflow(uri, {})
.setHandler(onresponse)
.start();
new JX.Workflow(widget_uri, {})
.setHandler(onwidgetresponse)
.start();
thread.visible = thread.selected;
}
function onwidgetresponse(response) {
var widgets = JX.$H(response.widgets);
var widgetsRoot = JX.$(config.widgets_pane);
JX.DOM.setContent(widgetsRoot, widgets);
}
function onresponse(response) {
var header = JX.$H(response.header);
var messages = JX.$H(response.messages);
var form = JX.$H(response.form);
var headerRoot = JX.$(config.header);
var messagesRoot = JX.$(config.messages);
var formRoot = JX.$(config.form_pane);
var widgetsRoot = JX.$(config.widgets_pane);
var menuRoot = JX.$(config.menu_pane);
JX.DOM.setContent(headerRoot, header);
JX.DOM.setContent(messagesRoot, messages);
messagesRoot.scrollTop = messagesRoot.scrollHeight;
JX.DOM.setContent(formRoot, form);
}
JX.Stratcom.listen(
'click',
'conpherence-menu-click',
function(e) {
e.kill();
selectthread(e.getNode('conpherence-menu-click'));
});
JX.Stratcom.listen('click', 'conpherence-edit-metadata', function (e) {
e.kill();
var root = JX.$(config.form_pane);
var form = JX.DOM.find(root, 'form');
var data = e.getNodeData('conpherence-edit-metadata');
new JX.Workflow.newFromForm(form, data)
.setHandler(function (r) {
// update the header
JX.DOM.setContent(
JX.$(config.header),
JX.$H(r.header)
);
// update the menu entry as well
JX.DOM.replace(
JX.$(r.conpherence_phid + '-nav-item'),
JX.$H(r.nav_item)
);
})
.start();
});
JX.Stratcom.listen('click', 'show-older-messages', function(e) {
e.kill();
var last_offset = e.getNodeData('show-older-messages').offset;
var conf_id = e.getNodeData('show-older-messages').ID;
JX.DOM.remove(e.getNode('show-older-messages'));
var messages_root = JX.$(config.messages);
new JX.Request('/conpherence/view/'+conf_id+'/', function(r) {
var messages = JX.$H(r.messages);
JX.DOM.prependContent(messages_root,
JX.$H(messages));
}).setData({ offset: last_offset+1 }).send();
});
// On mobile, we just show a thread list, so we don't want to automatically
// select or load any threads. On Desktop, we automatically select the first
// thread.
function ondevicechange() {
if (JX.Device.getDevice() != 'desktop') {
return;
}
// If there's no thread selected yet, select the first thread.
if (!thread.selected) {
var threads = JX.DOM.scry(document.body, 'a', 'conpherence-menu-click');
if (threads.length) {
selectthread(threads[0]);
}
}
// We might have a selected but undrawn thread for
redrawthread();
}
JX.Stratcom.listen('phabricator-device-change', null, ondevicechange);
ondevicechange();
// If there's a currently visible thread, select it.
- if (config.selected_conpherence_id) {
- var threads = JX.DOM.scry(document.body, 'a', 'conpherence-menu-click');
- for (var ii = 0; ii < threads.length; ii++) {
- var data = JX.Stratcom.getData(threads[ii]);
- if (data.phid == config.selected_conpherence_id) {
- selectthread(threads[ii]);
- break;
- }
- }
+ if (config.selectedID) {
+ selectthreadid(config.selectedID);
}
});
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Jan 19, 17:39 (1 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1127055
Default Alt Text
(19 KB)
Attached To
Mode
rP Phorge
Attached
Detach File
Event Timeline
Log In to Comment