Skip to content
This repository was archived by the owner on Jul 23, 2019. It is now read-only.

Commit b61a159

Browse files
Antonio ScandurraNathan Sobo
andcommitted
Get the discussion model in place in xray_core
Co-Authored-By: Nathan Sobo <nathan@github.com>
1 parent 789402a commit b61a159

File tree

6 files changed

+320
-23
lines changed

6 files changed

+320
-23
lines changed

xray_core/src/buffer_view.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,13 @@ use std::ops::Range;
1010
use std::rc::Rc;
1111
use window::{View, WeakViewHandle, Window};
1212

13-
pub struct BufferView {
13+
pub trait BufferViewDelegate {
14+
fn set_active_buffer_view(&mut self, buffer_view: WeakViewHandle<BufferView<Self>>)
15+
where
16+
Self: Sized;
17+
}
18+
19+
pub struct BufferView<T: BufferViewDelegate> {
1420
buffer: Rc<RefCell<Buffer>>,
1521
updates_tx: NotifyCell<()>,
1622
updates_rx: Box<Stream<Item = (), Error = ()>>,
@@ -20,6 +26,7 @@ pub struct BufferView {
2026
width: Option<f64>,
2127
line_height: f64,
2228
scroll_top: f64,
29+
delegate: Option<WeakViewHandle<T>>,
2330
}
2431

2532
#[derive(Debug, Eq, PartialEq, Serialize)]
@@ -50,8 +57,8 @@ enum BufferViewAction {
5057
AddSelectionBelow,
5158
}
5259

53-
impl BufferView {
54-
pub fn new(buffer: Rc<RefCell<Buffer>>) -> Self {
60+
impl<T: BufferViewDelegate> BufferView<T> {
61+
pub fn new(buffer: Rc<RefCell<Buffer>>, delegate: Option<WeakViewHandle<T>>) -> Self {
5562
let selection_set_id = {
5663
let mut buffer = buffer.borrow_mut();
5764
let start = buffer.anchor_before_offset(0).unwrap();
@@ -76,6 +83,7 @@ impl BufferView {
7683
width: None,
7784
line_height: 10.0,
7885
scroll_top: 0.0,
86+
delegate,
7987
}
8088
}
8189

@@ -551,13 +559,16 @@ impl BufferView {
551559
}
552560
}
553561

554-
impl View for BufferView {
562+
impl<T: BufferViewDelegate> View for BufferView<T> {
555563
fn component_name(&self) -> &'static str {
556564
"BufferView"
557565
}
558566

559-
fn will_mount(&mut self, window: &mut Window, _: WeakViewHandle<Self>) {
567+
fn will_mount(&mut self, window: &mut Window, self_handle: WeakViewHandle<Self>) {
560568
self.height = Some(window.height());
569+
if let Some(ref delegate) = self.delegate {
570+
delegate.map(|delegate| delegate.set_active_buffer_view(self_handle));
571+
}
561572
}
562573

563574
fn render(&self) -> serde_json::Value {
@@ -631,7 +642,7 @@ impl View for BufferView {
631642
}
632643
}
633644

634-
impl Stream for BufferView {
645+
impl<T: BufferViewDelegate> Stream for BufferView<T> {
635646
type Item = ();
636647
type Error = ();
637648

@@ -640,7 +651,7 @@ impl Stream for BufferView {
640651
}
641652
}
642653

643-
impl Drop for BufferView {
654+
impl<T: BufferViewDelegate> Drop for BufferView<T> {
644655
fn drop(&mut self) {
645656
self.buffer
646657
.borrow_mut()

xray_core/src/discussion.rs

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
use futures::{unsync, Async, Future, Poll, Stream};
2+
use never::Never;
3+
use notify_cell::NotifyCell;
4+
use project;
5+
use rpc::{self, client, server};
6+
use serde_json;
7+
use std::cell::RefCell;
8+
use std::rc::Rc;
9+
use window::{View, WeakViewHandle, Window};
10+
use workspace::UserId;
11+
use ForegroundExecutor;
12+
use IntoShared;
13+
14+
pub trait DiscussionViewDelegate {
15+
fn anchor(&self) -> Option<project::Anchor>;
16+
fn jump(&self, anchor: &project::Anchor) -> Option<project::Anchor>;
17+
}
18+
19+
pub struct Discussion {
20+
messages: Vec<Message>,
21+
local_user_id: UserId,
22+
outgoing_message_txs: Vec<unsync::mpsc::UnboundedSender<Message>>,
23+
updates: NotifyCell<()>,
24+
client: Option<client::Service<DiscussionService>>,
25+
}
26+
27+
#[derive(Clone, Serialize, Deserialize)]
28+
pub struct Message {
29+
text: String,
30+
anchor: Option<project::Anchor>,
31+
user_id: UserId,
32+
}
33+
34+
pub struct DiscussionView<T: DiscussionViewDelegate> {
35+
discussion: Rc<RefCell<Discussion>>,
36+
updates: Box<Stream<Item = (), Error = ()>>,
37+
delegate: WeakViewHandle<T>,
38+
}
39+
40+
#[derive(Deserialize)]
41+
#[serde(tag = "type")]
42+
enum DiscussionViewAction {
43+
Send { text: String },
44+
Jump { message_index: usize },
45+
}
46+
47+
pub struct DiscussionService {
48+
remote_user_id: UserId,
49+
discussion: Rc<RefCell<Discussion>>,
50+
outgoing_messages: Box<Stream<Item = Message, Error = Never>>,
51+
}
52+
53+
#[derive(Serialize, Deserialize)]
54+
pub struct ServiceRequest {
55+
text: String,
56+
anchor: Option<project::Anchor>,
57+
}
58+
59+
impl Discussion {
60+
pub fn new(local_user_id: UserId) -> Self {
61+
Self {
62+
messages: Vec::new(),
63+
local_user_id,
64+
outgoing_message_txs: Vec::new(),
65+
updates: NotifyCell::new(()),
66+
client: None,
67+
}
68+
}
69+
70+
pub fn remote(
71+
executor: ForegroundExecutor,
72+
local_user_id: UserId,
73+
client: client::Service<DiscussionService>,
74+
) -> Result<Rc<RefCell<Self>>, rpc::Error> {
75+
let client_updates = client.updates()?;
76+
let discussion = Self {
77+
messages: client.state()?,
78+
local_user_id,
79+
outgoing_message_txs: Vec::new(),
80+
updates: NotifyCell::new(()),
81+
client: Some(client),
82+
}.into_shared();
83+
84+
let discussion_weak = Rc::downgrade(&discussion);
85+
executor.execute(Box::new(client_updates.for_each(move |message| {
86+
if let Some(discussion) = discussion_weak.upgrade() {
87+
discussion.borrow_mut().push_message(message);
88+
}
89+
90+
Ok(())
91+
})));
92+
Ok(discussion)
93+
}
94+
95+
fn updates(&self) -> impl Stream<Item = (), Error = ()> {
96+
self.updates.observe()
97+
}
98+
99+
fn outgoing_messages(&mut self) -> impl Stream<Item = Message, Error = Never> {
100+
let (tx, rx) = unsync::mpsc::unbounded();
101+
self.outgoing_message_txs.push(tx);
102+
rx.map_err(|_| unreachable!())
103+
}
104+
105+
fn send(&mut self, text: String, anchor: Option<project::Anchor>) {
106+
if let Some(ref client) = self.client {
107+
client.request(ServiceRequest { text, anchor });
108+
} else {
109+
let user_id = self.local_user_id;
110+
self.push_message(Message {
111+
text,
112+
anchor,
113+
user_id,
114+
});
115+
}
116+
}
117+
118+
fn push_message(&mut self, message: Message) {
119+
self.outgoing_message_txs
120+
.retain(|tx| !tx.unbounded_send(message.clone()).is_err());
121+
self.messages.push(message);
122+
self.updates.set(());
123+
}
124+
}
125+
126+
impl<T: DiscussionViewDelegate> View for DiscussionView<T> {
127+
fn component_name(&self) -> &'static str {
128+
"Discussion"
129+
}
130+
131+
fn render(&self) -> serde_json::Value {
132+
let discussion = self.discussion.borrow();
133+
json!({
134+
"messages": discussion.messages.iter().enumerate().map(|(index, message)| json!({
135+
"index": index,
136+
"text": message.text,
137+
"user_id": message.user_id
138+
})).collect::<Vec<_>>()
139+
})
140+
}
141+
142+
fn dispatch_action(&mut self, action: serde_json::Value, _: &mut Window) {
143+
match serde_json::from_value(action) {
144+
Ok(DiscussionViewAction::Send { text }) => {
145+
if let Some(anchor) = self.delegate.map(|delegate| delegate.anchor()) {
146+
self.discussion.borrow_mut().send(text, anchor);
147+
}
148+
}
149+
Ok(DiscussionViewAction::Jump { message_index }) => {
150+
let discussion = self.discussion.borrow();
151+
let message = &discussion.messages[message_index];
152+
self.delegate.map(|delegate| {
153+
if let Some(ref anchor) = message.anchor {
154+
delegate.jump(anchor);
155+
}
156+
});
157+
}
158+
_ => eprintln!("Unrecognized action"),
159+
}
160+
}
161+
}
162+
163+
impl<T: DiscussionViewDelegate> DiscussionView<T> {
164+
pub fn new(discussion: Rc<RefCell<Discussion>>, delegate: WeakViewHandle<T>) -> Self {
165+
let updates = discussion.borrow().updates();
166+
Self {
167+
delegate,
168+
discussion,
169+
updates: Box::new(updates),
170+
}
171+
}
172+
}
173+
174+
impl<T: DiscussionViewDelegate> Stream for DiscussionView<T> {
175+
type Item = ();
176+
type Error = ();
177+
178+
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
179+
self.updates.poll()
180+
}
181+
}
182+
183+
impl DiscussionService {
184+
pub fn new(remote_user_id: UserId, discussion: Rc<RefCell<Discussion>>) -> Self {
185+
let outgoing_messages = Box::new(discussion.borrow_mut().outgoing_messages());
186+
Self {
187+
remote_user_id,
188+
discussion,
189+
outgoing_messages,
190+
}
191+
}
192+
}
193+
194+
impl server::Service for DiscussionService {
195+
type State = Vec<Message>;
196+
type Update = Message;
197+
type Request = ServiceRequest;
198+
type Response = ();
199+
200+
fn init(&mut self, _: &rpc::server::Connection) -> Self::State {
201+
self.discussion.borrow().messages.clone()
202+
}
203+
204+
fn poll_update(&mut self, _: &rpc::server::Connection) -> Async<Option<Self::Update>> {
205+
self.outgoing_messages.poll().unwrap()
206+
}
207+
208+
fn request(
209+
&mut self,
210+
request: Self::Request,
211+
_connection: &rpc::server::Connection,
212+
) -> Option<Box<Future<Item = Self::Response, Error = Never>>> {
213+
self.discussion.borrow_mut().push_message(Message {
214+
text: request.text,
215+
anchor: request.anchor,
216+
user_id: self.remote_user_id,
217+
});
218+
None
219+
}
220+
}

xray_core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pub mod rpc;
3333
pub mod window;
3434
pub mod workspace;
3535

36+
mod discussion;
3637
mod file_finder;
3738
mod fuzzy;
3839
mod movement;

xray_core/src/never.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
#[derive(Serialize, Deserialize)]
1+
#[derive(Debug, Serialize, Deserialize)]
22
pub enum Never {}

xray_core/src/project.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use std::cmp;
1111
use std::collections::{BinaryHeap, HashMap};
1212
use std::error::Error;
1313
use std::io;
14+
use std::ops::Range;
1415
use std::rc::Rc;
1516
use std::sync::Arc;
1617
use ForegroundExecutor;
@@ -45,6 +46,13 @@ pub struct RemoteProject {
4546
trees: HashMap<TreeId, Box<fs::Tree>>,
4647
}
4748

49+
#[derive(Clone, Serialize, Deserialize)]
50+
pub struct Anchor {
51+
tree_id: TreeId,
52+
relative_path: cross_platform::Path,
53+
range: Range<buffer::Anchor>,
54+
}
55+
4856
pub struct ProjectService {
4957
project: Rc<RefCell<LocalProject>>,
5058
tree_services: HashMap<TreeId, rpc::server::ServiceHandle>,

0 commit comments

Comments
 (0)