Compare commits
10 Commits
bd829f23ad
...
1d178d6bd9
Author | SHA1 | Date | |
---|---|---|---|
|
1d178d6bd9 | ||
|
98215b06d2 | ||
|
397611424e | ||
|
191f56a606 | ||
|
e70648571f | ||
|
9774795bb2 | ||
|
dee25f911b | ||
|
445b21975a | ||
|
70b163cf81 | ||
|
431b062420 |
19
.gitlab-ci.yml
Normal file
19
.gitlab-ci.yml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
stages:
|
||||||
|
- armv6
|
||||||
|
|
||||||
|
variables:
|
||||||
|
DOCKER_HOST: tcp://docker:2375/
|
||||||
|
DOCKER_DRIVER: overlay2
|
||||||
|
CROSS_REMOTE: 1
|
||||||
|
DOCKER_TLS_CERTDIR: ""
|
||||||
|
|
||||||
|
services:
|
||||||
|
- docker:18.09-dind
|
||||||
|
|
||||||
|
armv6:
|
||||||
|
stage: armv6
|
||||||
|
image: ghcr.io/cross-rs/x86_64-unknown-linux-gnu:main
|
||||||
|
only:
|
||||||
|
- dev/gitlab-cross-ci
|
||||||
|
script:
|
||||||
|
- cross test --target arm-unknown-linux-gnueabihf
|
41
Cargo.lock
generated
41
Cargo.lock
generated
@ -140,27 +140,25 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures-channel"
|
||||||
version = "0.3.16"
|
version = "0.3.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "74ed2411805f6e4e3d9bc904c95d5d423b89b3b25dc0250aa74729de20629ff9"
|
checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.16"
|
version = "0.3.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "af51b1b4a7fdff033703db39de8802c673eb91855f2e0d47dcf3bf2c0ef01f99"
|
checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-macro"
|
name = "futures-macro"
|
||||||
version = "0.3.16"
|
version = "0.3.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c54913bae956fb8df7f4dc6fc90362aa72e69148e3f39041fbe8742d21e0ac57"
|
checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
|
||||||
"proc-macro-hack",
|
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
@ -168,30 +166,27 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-sink"
|
||||||
version = "0.3.16"
|
version = "0.3.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c0f30aaa67363d119812743aa5f33c201a7a66329f97d1a887022971feea4b53"
|
checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-task"
|
name = "futures-task"
|
||||||
version = "0.3.16"
|
version = "0.3.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bbe54a98670017f3be909561f6ad13e810d9a51f3f061b902062ca3da80799f2"
|
checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-util"
|
name = "futures-util"
|
||||||
version = "0.3.16"
|
version = "0.3.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "67eb846bfd58e44a8481a00049e82c43e0ccb5d61f8dc071057cb19249dd4d78"
|
checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-macro",
|
"futures-macro",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"pin-utils",
|
"pin-utils",
|
||||||
"proc-macro-hack",
|
|
||||||
"proc-macro-nested",
|
|
||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -496,18 +491,6 @@ dependencies = [
|
|||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro-hack"
|
|
||||||
version = "0.5.20+deprecated"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro-nested"
|
|
||||||
version = "0.1.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.28"
|
version = "1.0.28"
|
||||||
|
@ -53,8 +53,7 @@ impl std::iter::Iterator for State {
|
|||||||
pub enum DeferredEvent {
|
pub enum DeferredEvent {
|
||||||
Quit,
|
Quit,
|
||||||
NewRepo(String),
|
NewRepo(String),
|
||||||
TagPrevious,
|
LoadMoreTags,
|
||||||
TagNext,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ui {
|
impl Ui {
|
||||||
@ -73,6 +72,8 @@ impl Ui {
|
|||||||
events: mpsc::Receiver<DeferredEvent>,
|
events: mpsc::Receiver<DeferredEvent>,
|
||||||
sender: mpsc::Sender<UiEvent>,
|
sender: mpsc::Sender<UiEvent>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
|
let fetching_tags = Arc::new(std::sync::atomic::AtomicBool::new(false));
|
||||||
loop {
|
loop {
|
||||||
match events.recv() {
|
match events.recv() {
|
||||||
Ok(DeferredEvent::Quit) => break,
|
Ok(DeferredEvent::Quit) => break,
|
||||||
@ -86,29 +87,39 @@ impl Ui {
|
|||||||
let mut ui = ui.lock().unwrap();
|
let mut ui = ui.lock().unwrap();
|
||||||
ui.tags = list;
|
ui.tags = list;
|
||||||
}
|
}
|
||||||
Ok(DeferredEvent::TagPrevious) => {
|
Ok(DeferredEvent::LoadMoreTags) if !fetching_tags.load(Ordering::Relaxed) => {
|
||||||
let mut ui = ui.lock().unwrap();
|
fetching_tags.store(true, Ordering::Relaxed);
|
||||||
ui.tags.previous();
|
let mut tags_copy = {
|
||||||
ui.details = ui.tags.create_detail_widget();
|
|
||||||
}
|
|
||||||
Ok(DeferredEvent::TagNext) => {
|
|
||||||
let (fetched_new_tags, mut tags) = {
|
|
||||||
let mut ui = ui.lock().unwrap();
|
let mut ui = ui.lock().unwrap();
|
||||||
if ui.tags.at_end_of_list() {
|
ui.info.set_text("Fetching more tags...");
|
||||||
ui.info.set_text("Fetching more tags...");
|
sender.send(UiEvent::RefreshOnNewData)?;
|
||||||
sender.send(UiEvent::RefreshOnNewData)?;
|
ui.tags.clone()
|
||||||
(true, ui.tags.clone())
|
|
||||||
} else {
|
|
||||||
(false, ui.tags.clone())
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
tags.next().await;
|
|
||||||
let mut ui = ui.lock().unwrap();
|
let sender_copy = sender.clone();
|
||||||
ui.tags = tags;
|
let ui_copy = ui.clone();
|
||||||
ui.details = ui.tags.create_detail_widget();
|
let fetching_tags_copy = fetching_tags.clone();
|
||||||
if fetched_new_tags {
|
std::thread::spawn(move || {
|
||||||
ui.info.set_text("Fetching tags done");
|
tokio::runtime::Builder::new_multi_thread()
|
||||||
}
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
.block_on(async {
|
||||||
|
tags_copy.load_next_page().await;
|
||||||
|
let mut ui = ui_copy.lock().unwrap();
|
||||||
|
//set position to the position of old TagList
|
||||||
|
//it may have changed since tag fetching has been invoked
|
||||||
|
tags_copy.set_cursor(ui.tags.get_cursor().clone());
|
||||||
|
ui.tags = tags_copy;
|
||||||
|
ui.details = ui.tags.create_detail_widget();
|
||||||
|
ui.info.set_text("Fetching tags done");
|
||||||
|
sender_copy.send(UiEvent::RefreshOnNewData).unwrap();
|
||||||
|
fetching_tags_copy.store(false, Ordering::Relaxed);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(DeferredEvent::LoadMoreTags) => {
|
||||||
|
//do nothing, as we are fetching tags
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let mut ui = ui.lock().unwrap();
|
let mut ui = ui.lock().unwrap();
|
||||||
@ -181,7 +192,7 @@ impl Ui {
|
|||||||
let (tags, state) = ui_data.tags.render(render_state);
|
let (tags, state) = ui_data.tags.render(render_state);
|
||||||
let more_chunks = Layout::default()
|
let more_chunks = Layout::default()
|
||||||
.direction(Direction::Horizontal)
|
.direction(Direction::Horizontal)
|
||||||
.constraints([Constraint::Min(15), Constraint::Length(28)].as_ref())
|
.constraints([Constraint::Min(15), Constraint::Length(30)].as_ref())
|
||||||
.split(chunks[1]);
|
.split(chunks[1]);
|
||||||
rect.render_stateful_widget(tags, more_chunks[0], state);
|
rect.render_stateful_widget(tags, more_chunks[0], state);
|
||||||
rect.render_widget(ui_data.details.render(), more_chunks[1]);
|
rect.render_widget(ui_data.details.render(), more_chunks[1]);
|
||||||
@ -223,12 +234,14 @@ impl Ui {
|
|||||||
}
|
}
|
||||||
//moving up on selecting tags
|
//moving up on selecting tags
|
||||||
Key::Up | Key::Char('k') if ui_data.state == State::SelectTag => {
|
Key::Up | Key::Char('k') if ui_data.state == State::SelectTag => {
|
||||||
deferred_sender.send(DeferredEvent::TagPrevious)?;
|
ui_data.tags.previous();
|
||||||
ui_data.details = ui_data.tags.create_detail_widget();
|
ui_data.details = ui_data.tags.create_detail_widget();
|
||||||
}
|
}
|
||||||
//moving down on selecting tags
|
//moving down on selecting tags
|
||||||
Key::Down | Key::Char('j') if ui_data.state == State::SelectTag => {
|
Key::Down | Key::Char('j') if ui_data.state == State::SelectTag => {
|
||||||
deferred_sender.send(DeferredEvent::TagNext)?;
|
if ui_data.tags.next().is_some() {
|
||||||
|
deferred_sender.send(DeferredEvent::LoadMoreTags).unwrap();
|
||||||
|
}
|
||||||
ui_data.details = ui_data.tags.create_detail_widget();
|
ui_data.details = ui_data.tags.create_detail_widget();
|
||||||
}
|
}
|
||||||
//append character on editing repository
|
//append character on editing repository
|
||||||
|
@ -58,8 +58,7 @@ impl std::iter::Iterator for State {
|
|||||||
pub enum DeferredEvent {
|
pub enum DeferredEvent {
|
||||||
Quit,
|
Quit,
|
||||||
NewRepo(String),
|
NewRepo(String),
|
||||||
TagPrevious,
|
LoadMoreTags,
|
||||||
TagNext,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ui {
|
impl Ui {
|
||||||
@ -78,6 +77,8 @@ impl Ui {
|
|||||||
events: mpsc::Receiver<DeferredEvent>,
|
events: mpsc::Receiver<DeferredEvent>,
|
||||||
sender: mpsc::Sender<UiEvent>,
|
sender: mpsc::Sender<UiEvent>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
|
let fetching_tags = Arc::new(std::sync::atomic::AtomicBool::new(false));
|
||||||
loop {
|
loop {
|
||||||
match events.recv() {
|
match events.recv() {
|
||||||
Ok(DeferredEvent::Quit) => break,
|
Ok(DeferredEvent::Quit) => break,
|
||||||
@ -91,29 +92,39 @@ impl Ui {
|
|||||||
let mut ui = ui.lock().unwrap();
|
let mut ui = ui.lock().unwrap();
|
||||||
ui.tags = list;
|
ui.tags = list;
|
||||||
}
|
}
|
||||||
Ok(DeferredEvent::TagPrevious) => {
|
Ok(DeferredEvent::LoadMoreTags) if !fetching_tags.load(Ordering::Relaxed) => {
|
||||||
let mut ui = ui.lock().unwrap();
|
fetching_tags.store(true, Ordering::Relaxed);
|
||||||
ui.tags.previous();
|
let mut tags_copy = {
|
||||||
ui.details = ui.tags.create_detail_widget();
|
|
||||||
}
|
|
||||||
Ok(DeferredEvent::TagNext) => {
|
|
||||||
let (fetched_new_tags, mut tags) = {
|
|
||||||
let mut ui = ui.lock().unwrap();
|
let mut ui = ui.lock().unwrap();
|
||||||
if ui.tags.at_end_of_list() {
|
ui.info.set_text("Fetching more tags...");
|
||||||
ui.info.set_text("Fetching more tags...");
|
sender.send(UiEvent::RefreshOnNewData)?;
|
||||||
sender.send(UiEvent::RefreshOnNewData)?;
|
ui.tags.clone()
|
||||||
(true, ui.tags.clone())
|
|
||||||
} else {
|
|
||||||
(false, ui.tags.clone())
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
tags.next().await;
|
|
||||||
let mut ui = ui.lock().unwrap();
|
let sender_copy = sender.clone();
|
||||||
ui.tags = tags;
|
let ui_copy = ui.clone();
|
||||||
ui.details = ui.tags.create_detail_widget();
|
let fetching_tags_copy = fetching_tags.clone();
|
||||||
if fetched_new_tags {
|
std::thread::spawn(move || {
|
||||||
ui.info.set_text("Fetching tags done");
|
tokio::runtime::Builder::new_multi_thread()
|
||||||
}
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
.block_on(async {
|
||||||
|
tags_copy.load_next_page().await;
|
||||||
|
let mut ui = ui_copy.lock().unwrap();
|
||||||
|
//set position to the position of old TagList
|
||||||
|
//it may have changed since tag fetching has been invoked
|
||||||
|
tags_copy.set_cursor(ui.tags.get_cursor().clone());
|
||||||
|
ui.tags = tags_copy;
|
||||||
|
ui.details = ui.tags.create_detail_widget();
|
||||||
|
ui.info.set_text("Fetching tags done");
|
||||||
|
sender_copy.send(UiEvent::RefreshOnNewData).unwrap();
|
||||||
|
fetching_tags_copy.store(false, Ordering::Relaxed);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(DeferredEvent::LoadMoreTags) => {
|
||||||
|
//do nothing, as we are fetching tags
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let mut ui = ui.lock().unwrap();
|
let mut ui = ui.lock().unwrap();
|
||||||
@ -312,11 +323,15 @@ impl Ui {
|
|||||||
}
|
}
|
||||||
//moving up on selecting tags
|
//moving up on selecting tags
|
||||||
Key::Up | Key::Char('k') if ui_data.state == State::SelectTag => {
|
Key::Up | Key::Char('k') if ui_data.state == State::SelectTag => {
|
||||||
deferred_sender.send(DeferredEvent::TagPrevious).unwrap();
|
ui_data.tags.previous();
|
||||||
|
ui_data.details = ui_data.tags.create_detail_widget();
|
||||||
}
|
}
|
||||||
//moving down on selecting tags
|
//moving down on selecting tags
|
||||||
Key::Down | Key::Char('j') if ui_data.state == State::SelectTag => {
|
Key::Down | Key::Char('j') if ui_data.state == State::SelectTag => {
|
||||||
deferred_sender.send(DeferredEvent::TagNext).unwrap();
|
if ui_data.tags.next().is_some() {
|
||||||
|
deferred_sender.send(DeferredEvent::LoadMoreTags).unwrap();
|
||||||
|
}
|
||||||
|
ui_data.details = ui_data.tags.create_detail_widget();
|
||||||
}
|
}
|
||||||
//append character on editing repository
|
//append character on editing repository
|
||||||
Key::Char(key) if ui_data.state == State::EditRepo => {
|
Key::Char(key) if ui_data.state == State::EditRepo => {
|
||||||
|
@ -86,11 +86,12 @@ impl TagList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn at_end_of_list(&self) -> bool {
|
pub fn set_cursor(&mut self, state: ListState) {
|
||||||
if let Some(i) = self.state.selected() {
|
self.state = state;
|
||||||
return i == self.lines.len() - 2;
|
}
|
||||||
}
|
|
||||||
false
|
pub fn get_cursor(&self) -> &ListState {
|
||||||
|
&self.state
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(&mut self, colored: bool) -> (List, &mut ListState) {
|
pub fn render(&mut self, colored: bool) -> (List, &mut ListState) {
|
||||||
@ -177,16 +178,19 @@ impl TagList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// select next tag
|
/// select next tag
|
||||||
pub async fn next(&mut self) {
|
/// returns Some when more tags need to be fetched otherwise None
|
||||||
|
pub fn next(&mut self) -> Option<()> {
|
||||||
if let Some(Line::Status(_)) = self.lines.get(0) {
|
if let Some(Line::Status(_)) = self.lines.get(0) {
|
||||||
return;
|
return None;
|
||||||
}
|
}
|
||||||
match self.state.selected() {
|
match self.state.selected() {
|
||||||
None if !self.lines.is_empty() => self.state.select(Some(0)),
|
None if !self.lines.is_empty() => self.state.select(Some(0)),
|
||||||
None => (),
|
None => (),
|
||||||
Some(i) if i == self.lines.len() - 2 => self.load_next_page().await,
|
Some(i) if i == self.lines.len() - 2 => return Some(()),
|
||||||
|
// Some(i) if i == self.lines.len() - 2 => return self.load_next_page().await,
|
||||||
Some(i) => self.state.select(Some(i + 1)),
|
Some(i) => self.state.select(Some(i + 1)),
|
||||||
}
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// select previous tag
|
/// select previous tag
|
||||||
|
@ -26,7 +26,7 @@ impl Details {
|
|||||||
let mut lines = vec![format!("{:^10}|{:^6}|{:^6}", "ARCH", "OS", "SIZE")];
|
let mut lines = vec![format!("{:^10}|{:^6}|{:^6}", "ARCH", "OS", "SIZE")];
|
||||||
for d in &self.details {
|
for d in &self.details {
|
||||||
lines.push(format!(
|
lines.push(format!(
|
||||||
"{:^10}|{:^6}|{:^6}MB",
|
"{:>10}|{:>6}|{:>6} MB",
|
||||||
format!(
|
format!(
|
||||||
"{}{}",
|
"{}{}",
|
||||||
d.arch.clone().unwrap_or_default(),
|
d.arch.clone().unwrap_or_default(),
|
||||||
|
Loading…
Reference in New Issue
Block a user