Skip to content

Commit aa1f57a

Browse files
authored
Merge pull request #241 from Berrysoft/remove-callback
Remove callback
2 parents 676d2bc + 25467cc commit aa1f57a

File tree

18 files changed

+277
-285
lines changed

18 files changed

+277
-285
lines changed

Cargo.lock

+63-78
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+2-3
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ chrono = { version = "0.4", default-features = false, features = [
4949
clap = { version = "4", features = ["derive"] }
5050
dirs = "5"
5151
log = "0.4"
52-
base64 = "0.21"
52+
base64 = "0.22"
5353

5454
futures-core = "0.3"
5555
futures-util = "0.3"
@@ -70,6 +70,5 @@ objc = "0.2"
7070
core-foundation = "0.9"
7171
system-configuration = "0.6"
7272

73-
windows = "0.53"
73+
windows = "0.54"
7474
winresource = "0.1"
75-

macbundle/Info.plist

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
<string>tunet-gui</string>
1818

1919
<key>CFBundleVersion</key>
20-
<string>0.9.2</string>
20+
<string>0.9.3</string>
2121
<key>CFBundleShortVersionString</key>
22-
<string>0.9.2</string>
22+
<string>0.9.3</string>
2323

2424
<key>LSMinimumSystemVersion</key>
2525
<string>11.7</string>

tunet-cui/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "tunet-cui"
3-
version = "0.9.2"
3+
version = "0.9.3"
44
description = "Tsinghua University network CUI"
55
edition.workspace = true
66
authors.workspace = true

tunet-cui/src/event.rs

+27-58
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
use anyhow::Result;
22
pub use crossterm::event::Event as TerminalEvent;
3-
use crossterm::event::{KeyCode, MouseButton, MouseEventKind};
4-
use futures_util::{pin_mut, Stream, StreamExt};
3+
use crossterm::event::{EventStream, KeyCode, MouseButton, MouseEventKind};
4+
use futures_util::StreamExt;
55
use ratatui::layout::Rect;
6-
use std::{
7-
pin::Pin,
8-
task::{Context, Poll},
9-
};
106
use tokio::sync::mpsc::*;
117
use tunet_model::*;
128

@@ -19,23 +15,21 @@ pub enum EventType {
1915

2016
pub struct Event {
2117
pub model: Model,
22-
tx: Sender<Result<EventType>>,
23-
rx: Receiver<Result<EventType>>,
18+
event: EventStream,
19+
mrx: Receiver<Action>,
20+
urx: Receiver<UpdateMsg>,
2421
}
2522

2623
impl Event {
2724
pub fn new() -> Result<Self> {
28-
let (tx, rx) = channel(32);
2925
let (mtx, mrx) = channel(32);
30-
let mut e = Self {
31-
model: Model::new(mtx)?,
32-
tx,
33-
rx,
34-
};
35-
e.attach_callback();
36-
e.spawn_terminal_event();
37-
e.spawn_model_action(mrx);
38-
Ok(e)
26+
let (utx, urx) = channel(32);
27+
Ok(Self {
28+
model: Model::new(mtx, utx)?,
29+
event: EventStream::new(),
30+
mrx,
31+
urx,
32+
})
3933
}
4034

4135
pub fn start(&self) {
@@ -45,39 +39,22 @@ impl Event {
4539
self.spawn_details();
4640
}
4741

48-
#[allow(clippy::single_match)]
49-
fn attach_callback(&mut self) {
50-
let tx = self.tx.clone();
51-
self.model.update = Some(Box::new(move |_model, msg| match msg {
52-
UpdateMsg::State => {
53-
let tx = tx.clone();
54-
tokio::spawn(async move { tx.send(Ok(EventType::UpdateState)).await.ok() });
55-
}
56-
_ => {}
57-
}));
58-
}
59-
60-
fn spawn_terminal_event(&self) {
61-
let tx = self.tx.clone();
62-
tokio::spawn(async move {
63-
let stream = crossterm::event::EventStream::new();
64-
pin_mut!(stream);
65-
while let Some(e) = stream.next().await {
66-
tx.send(e.map(EventType::TerminalEvent).map_err(anyhow::Error::from))
67-
.await?;
68-
}
69-
Ok::<_, anyhow::Error>(())
70-
});
71-
}
72-
73-
fn spawn_model_action(&self, mut mrx: Receiver<Action>) {
74-
let tx = self.tx.clone();
75-
tokio::spawn(async move {
76-
while let Some(a) = mrx.recv().await {
77-
tx.send(Ok(EventType::ModelAction(a))).await?;
42+
pub async fn next_event(&mut self) -> Result<Option<EventType>> {
43+
loop {
44+
tokio::select! {
45+
e = self.event.next() => break if let Some(e) = e {
46+
Ok(Some(EventType::TerminalEvent(e?)))
47+
} else {
48+
Ok(None)
49+
},
50+
a = self.mrx.recv() => break Ok(a.map(EventType::ModelAction)),
51+
u = self.urx.recv() => match u {
52+
None => break Ok(None),
53+
Some(UpdateMsg::State) => break Ok(Some(EventType::UpdateState)),
54+
_ => {}
55+
},
7856
}
79-
Ok::<_, anyhow::Error>(())
80-
});
57+
}
8158
}
8259

8360
fn spawn_watch_status(&self) {
@@ -153,11 +130,3 @@ impl Event {
153130
true
154131
}
155132
}
156-
157-
impl Stream for Event {
158-
type Item = Result<EventType>;
159-
160-
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
161-
self.rx.poll_recv(cx)
162-
}
163-
}

tunet-cui/src/main.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use crossterm::{
77
execute,
88
terminal::*,
99
};
10-
use futures_util::TryStreamExt;
1110
use ratatui::{
1211
backend::{Backend, CrosstermBackend},
1312
layout::*,
@@ -87,7 +86,7 @@ async fn main_loop<B: Backend>(
8786
_ = interval.tick() => {
8887
terminal.draw(|f| view::draw(&event.model, f))?;
8988
}
90-
e = event.try_next() => {
89+
e = event.next_event() => {
9190
if let Some(e) = e? {
9291
if !event.handle(e, terminal.size()?) {
9392
break;

tunet-flutter/lib/runtime.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ class ManagedRuntime extends NotifyPropertyChanged {
131131
} else {
132132
await RustLib.init();
133133
}
134-
final runtime = await Runtime.newRuntime();
134+
final runtime = Runtime();
135135
return ManagedRuntime(runtime: runtime);
136136
}
137137

tunet-flutter/native/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ anyhow = { workspace = true }
1717
tokio = { workspace = true, features = ["rt-multi-thread"] }
1818
log = { workspace = true }
1919
chrono = { workspace = true }
20-
flutter_rust_bridge = { version = "=2.0.0-dev.26", features = ["chrono"] }
20+
flutter_rust_bridge = { version = "=2.0.0-dev.27", features = ["chrono"] }
2121

2222
[target.'cfg(target_os = "android")'.dependencies]
2323
android_logger = "0.13"

tunet-flutter/native/src/api.rs

+76-56
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,14 @@ pub struct RuntimeStartConfig {
122122
}
123123

124124
pub struct Runtime {
125-
pub rx: RustOpaque<Mutex<Option<mpsc::Receiver<Action>>>>,
125+
pub arx: RustOpaque<Mutex<Option<mpsc::Receiver<Action>>>>,
126+
pub urx: RustOpaque<Mutex<Option<mpsc::Receiver<UpdateMsg>>>>,
126127
pub model: RustOpaque<Mutex<Model>>,
127128
pub handle: RustOpaque<Mutex<Option<Handle>>>,
128129
}
129130

130131
impl Runtime {
132+
#[frb(sync)]
131133
pub fn new() -> Result<Runtime> {
132134
#[cfg(target_os = "android")]
133135
android_logger::init_once(
@@ -144,18 +146,21 @@ impl Runtime {
144146
.level_filter(log::LevelFilter::Trace)
145147
.init()?;
146148

147-
let (tx, rx) = mpsc::channel(32);
148-
let model = Model::new(tx)?;
149+
let (atx, arx) = mpsc::channel(32);
150+
let (utx, urx) = mpsc::channel(32);
151+
let model = Model::new(atx, utx)?;
149152
Ok(Self {
150-
rx: RustOpaque::new(Mutex::new(Some(rx))),
153+
arx: RustOpaque::new(Mutex::new(Some(arx))),
154+
urx: RustOpaque::new(Mutex::new(Some(urx))),
151155
model: RustOpaque::new(Mutex::new(model)),
152156
handle: RustOpaque::new(Mutex::new(None)),
153157
})
154158
}
155159

156160
pub fn start(&self, sink: StreamSink<UpdateMsgWrap>, config: RuntimeStartConfig) {
157161
let model = self.model.clone();
158-
let mut rx = self.rx.lock().unwrap().take().unwrap();
162+
let mut arx = self.arx.lock().unwrap().take().unwrap();
163+
let mut urx = self.urx.lock().unwrap().take().unwrap();
159164
let runtime = tokio::runtime::Builder::new_multi_thread()
160165
.worker_threads(1)
161166
.enable_all()
@@ -166,66 +171,81 @@ impl Runtime {
166171
std::thread::spawn(move || {
167172
runtime.block_on(async {
168173
{
169-
let mut model = model.lock().unwrap();
170-
model.update = Some(Box::new(move |model, msg| {
171-
let msg = match msg {
172-
UpdateMsg::Credential => {
173-
UpdateMsgWrap::Credential(model.username.clone())
174-
}
175-
UpdateMsg::State => UpdateMsgWrap::State(model.state),
176-
UpdateMsg::Status => UpdateMsgWrap::Status(model.status.to_string()),
177-
UpdateMsg::Log => UpdateMsgWrap::Log(model.log.to_string()),
178-
UpdateMsg::Flux => UpdateMsgWrap::Flux(model.flux.clone()),
179-
UpdateMsg::Online => UpdateMsgWrap::Online(
180-
model
181-
.users
182-
.iter()
183-
.map(|u| NetUserWrap {
184-
address: u.address.into(),
185-
address_v6: u.address_v6.into(),
186-
login_time: u.login_time,
187-
mac_address: u
188-
.mac_address
189-
.map(|addr| addr.to_string())
190-
.unwrap_or_default(),
191-
flux: u.flux,
192-
is_local: model
193-
.mac_addrs
174+
let model = model.clone();
175+
tokio::spawn(async move {
176+
while let Some(msg) = urx.recv().await {
177+
let msg = {
178+
let model = model.lock().unwrap();
179+
match msg {
180+
UpdateMsg::Credential => {
181+
UpdateMsgWrap::Credential(model.username.clone())
182+
}
183+
UpdateMsg::State => UpdateMsgWrap::State(model.state),
184+
UpdateMsg::Status => {
185+
UpdateMsgWrap::Status(model.status.to_string())
186+
}
187+
UpdateMsg::Log => UpdateMsgWrap::Log(model.log.to_string()),
188+
UpdateMsg::Flux => UpdateMsgWrap::Flux(model.flux.clone()),
189+
UpdateMsg::Online => UpdateMsgWrap::Online(
190+
model
191+
.users
194192
.iter()
195-
.any(|it| Some(it) == u.mac_address.as_ref()),
196-
})
197-
.collect(),
198-
),
199-
UpdateMsg::Details => UpdateMsgWrap::Details(model.details.clone(), {
200-
let data = DetailDaily::new(&model.details);
201-
DetailDailyWrap {
202-
details: data
203-
.details
204-
.into_iter()
205-
.map(|(date, flux)| DetailDailyPoint {
206-
day: date.day(),
207-
flux,
193+
.map(|u| NetUserWrap {
194+
address: u.address.into(),
195+
address_v6: u.address_v6.into(),
196+
login_time: u.login_time,
197+
mac_address: u
198+
.mac_address
199+
.map(|addr| addr.to_string())
200+
.unwrap_or_default(),
201+
flux: u.flux,
202+
is_local: model
203+
.mac_addrs
204+
.iter()
205+
.any(|it| Some(it) == u.mac_address.as_ref()),
206+
})
207+
.collect(),
208+
),
209+
UpdateMsg::Details => {
210+
UpdateMsgWrap::Details(model.details.clone(), {
211+
let data = DetailDaily::new(&model.details);
212+
DetailDailyWrap {
213+
details: data
214+
.details
215+
.into_iter()
216+
.map(|(date, flux)| DetailDailyPoint {
217+
day: date.day(),
218+
flux,
219+
})
220+
.collect(),
221+
now_month: data.now.month(),
222+
now_day: data.now.day(),
223+
max_flux: data.max_flux,
224+
}
208225
})
209-
.collect(),
210-
now_month: data.now.month(),
211-
now_day: data.now.day(),
212-
max_flux: data.max_flux,
226+
}
227+
UpdateMsg::LogBusy => UpdateMsgWrap::LogBusy(model.log_busy()),
228+
UpdateMsg::OnlineBusy => {
229+
UpdateMsgWrap::OnlineBusy(model.online_busy())
230+
}
231+
UpdateMsg::DetailBusy => {
232+
UpdateMsgWrap::DetailBusy(model.detail_busy())
233+
}
213234
}
214-
}),
215-
UpdateMsg::LogBusy => UpdateMsgWrap::LogBusy(model.log_busy()),
216-
UpdateMsg::OnlineBusy => UpdateMsgWrap::OnlineBusy(model.online_busy()),
217-
UpdateMsg::DetailBusy => UpdateMsgWrap::DetailBusy(model.detail_busy()),
218-
};
219-
sink.add(msg).unwrap();
220-
}));
221-
235+
};
236+
sink.add(msg).unwrap();
237+
}
238+
});
239+
}
240+
{
241+
let model = model.lock().unwrap();
222242
if (!config.username.is_empty()) && (!config.password.is_empty()) {
223243
model.queue(Action::Credential(config.username, config.password));
224244
}
225245
model.queue(Action::Status(Some(config.status)));
226246
model.queue(Action::Timer);
227247
}
228-
while let Some(action) = rx.recv().await {
248+
while let Some(action) = arx.recv().await {
229249
log::debug!("received action: {:?}", action);
230250
model.lock().unwrap().handle(action);
231251
}

tunet-flutter/pubspec.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
1515
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
1616
# Read more about iOS versioning at
1717
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
18-
version: 0.9.2+1
18+
version: 0.9.3+1
1919

2020
environment:
2121
sdk: ">=3.0.0 <4.0.0"
@@ -31,7 +31,7 @@ dependencies:
3131
sdk: flutter
3232

3333
ffi: ^2.1.0
34-
flutter_rust_bridge: 2.0.0-dev.26
34+
flutter_rust_bridge: 2.0.0-dev.27
3535
meta: ^1.9.1
3636
uuid: ^4.1.0
3737
freezed_annotation: ^2.2.0

tunet-gui/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "tunet-gui"
3-
version = "0.9.2"
3+
version = "0.9.3"
44
description = "Tsinghua University network GUI"
55
edition.workspace = true
66
authors.workspace = true

0 commit comments

Comments
 (0)