From 650179fd8794f9a3a6561916aafd5ec1fe7e27bb Mon Sep 17 00:00:00 2001 From: cht <3237126351@qq.com> Date: Wed, 8 Dec 2021 22:13:06 +0800 Subject: [PATCH] first tag --- README.md | 26 +++++++++- src/state.rs | 18 +++++-- src/subscribe/appsub.rs | 15 +++++- src/subscribe/render.rs | 12 ++--- src/subscribe/state.rs | 102 +++++++++++++++++----------------------- src/utils.rs | 48 +++++++++++-------- 6 files changed, 130 insertions(+), 91 deletions(-) diff --git a/README.md b/README.md index b9a4a57..880599d 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,28 @@ ### v2ray tui 界面,静态编译 -TODO +tui界面的v2ray + +按键 + +* h + * 按h出设置界面,设置界面里面有两个设置 + * v2raycore + * 订阅,当在第二个设置里面添加了订阅后按下键可以选中订阅,d键删除 +* e + * TODO, 计划作为设置 +* s + * 进入选择节点界面 + * 此界面按F5可以运行core,ese+q退出后设置代理可以访问互联网 + * 此界面左右键可以切换订阅 +* ese + q + * 此两键各种退出 + +使用 + +```sh +export http_proxy=http://127.0.0.1:8889 +export https_proxy=http://127.0.0.1:8889 +``` + +然后可以联网 diff --git a/src/state.rs b/src/state.rs index 95b5f79..9838bc6 100644 --- a/src/state.rs +++ b/src/state.rs @@ -7,6 +7,7 @@ use std::io; use std::io::Stdout; use tui::backend::CrosstermBackend; use tui::Terminal; +use tui::widgets::ListState; #[derive(Clone, Copy)] pub enum Page { SubScribe = 0, @@ -25,13 +26,22 @@ pub fn run_app(terminal: &mut Terminal) -> io::Result<()> { let mut appsub = AppSub::default(); let informations = utils::start(); if !informations.is_empty() { - appsub.subs[0] = informations + //appsub.subs[0] = informations[0] + // .iter() + // .map(|amessage| spider::remove_quotation(amessage.ps.clone())) + // .collect(); + appsub.subs = informations .iter() - .map(|amessage| spider::remove_quotation(amessage.ps.clone())) + .map(|ainformation| ainformation + .iter() + .map(|message| spider::remove_quotation(message.ps.clone())) + .collect()) .collect(); appsub.stateoflist = true; - appsub.state[0].select(Some(0)); - appsub.informations[0] = informations; + let len = informations.len(); + appsub.state = vec![ListState::default();len]; + //appsub.state[0].select(Some(0)); + appsub.informations = informations.clone(); } appsub.subscription = utils::get_subs(); appsub.settings_input[0] = utils::start_v2core(); diff --git a/src/subscribe/appsub.rs b/src/subscribe/appsub.rs index 8ab851b..f55fa93 100644 --- a/src/subscribe/appsub.rs +++ b/src/subscribe/appsub.rs @@ -64,7 +64,20 @@ impl AppSub { }; self.state[self.subsindex].select(Some(i)); } - + pub fn left(&mut self){ + if self.subsindex == 0 { + self.subsindex = self.state.len()-1; + } else { + self.subsindex -=1; + } + } + pub fn right(&mut self){ + if self.subsindex >= self.state.len() -1 { + self.subsindex = 0; + } else { + self.subsindex +=1; + } + } pub fn unselect(&mut self) { self.state[self.subsindex].select(None); } diff --git a/src/subscribe/render.rs b/src/subscribe/render.rs index d23e2b0..f6d5cf9 100644 --- a/src/subscribe/render.rs +++ b/src/subscribe/render.rs @@ -68,7 +68,7 @@ pub(crate) fn ui(f: &mut Frame, app: &mut AppSub) { InputMode::Editing => Style::default().fg(Color::Yellow), _ => Style::default(), }) - .block(Block::default().borders(Borders::ALL).title("Input")); + .block(Block::default().borders(Borders::ALL).title("Search bar")); f.render_widget(input, chunks[1]); if let InputMode::Editing = app.input_mode { // Make the cursor visible and ask tui-rs to put it at the specified coordinates after rendering @@ -78,8 +78,6 @@ pub(crate) fn ui(f: &mut Frame, app: &mut AppSub) { // Move one line down, from the border to the input line chunks[1].y + 1, ) - //InputMode::Normal | InputMode::Select | InputMode::Popup => - // Hide the cursor. `Frame` does this by default, so we don't need to do anything here } // Bottom two inner blocks @@ -89,7 +87,7 @@ pub(crate) fn ui(f: &mut Frame, app: &mut AppSub) { .split(chunks[2]); let subs: Vec = app - .subs[0] + .subs[app.subsindex] .iter() .enumerate() .map(|(i, m)| { @@ -98,7 +96,7 @@ pub(crate) fn ui(f: &mut Frame, app: &mut AppSub) { }) .collect(); let subs = List::new(subs) - .block(Block::default().borders(Borders::ALL).title("List")) + .block(Block::default().borders(Borders::ALL).title(format!("Subscribe {}",app.subsindex))) .highlight_style( Style::default() .bg(Color::LightGreen) @@ -118,10 +116,10 @@ pub(crate) fn ui(f: &mut Frame, app: &mut AppSub) { }) .collect(); let block = - List::new(messages).block(Block::default().borders(Borders::ALL).title("Messages")); + List::new(messages).block(Block::default().borders(Borders::ALL).title("Informations")); f.render_widget(block, bottom_chunks[1]); } else { - let block = Block::default().title("With borders").borders(Borders::ALL); + let block = Block::default().title("Informations None").borders(Borders::ALL); f.render_widget(block, bottom_chunks[1]); } //}; diff --git a/src/subscribe/state.rs b/src/subscribe/state.rs index f2f76ce..e73ad4a 100644 --- a/src/subscribe/state.rs +++ b/src/subscribe/state.rs @@ -4,6 +4,7 @@ use super::utils; use super::{Page, IFEXIT}; use crossterm::event::{self, Event, KeyCode}; use std::{env, io, process::Command}; +use tui::widgets::ListState; pub(crate) fn subscribe_state(app: &mut AppSub) -> io::Result { if let Event::Key(key) = event::read()? { match app.input_mode { @@ -30,38 +31,7 @@ pub(crate) fn subscribe_state(app: &mut AppSub) -> io::Result { }, InputMode::Editing => match key.code { KeyCode::Enter => { - let input = vec![app.input.clone()]; - let get_list = spider::get_the_key(input); - if let Ok(list) = get_list { - let mut storge: String = String::new(); - storge.push('['); - storge.push('\n'); - if !list[0].is_empty() { - //app.subs = list[0].clone(); - app.stateoflist = true; - app.state[app.subsindex].select(Some(0)); - for alist in &list[0] { - let information = spider::Information::new(alist.to_string()); - app.informations[0].push(information.clone()); - storge.push_str(information.get_the_json_node().as_str()); - } - app.subs[0] = app - .informations[0] - .iter() - .map(|ainformation| { - spider::remove_quotation(ainformation.ps.clone()) - }) - .collect(); - } - storge.pop(); - storge.pop(); - storge.push('\n'); - storge.push(']'); - utils::create_json_file(utils::Save::Storage, storge) - .unwrap_or_else(|err| panic!("err {}", err)); - } - - //app.subs.push(app.input.drain(..).collect()); + app.input = "This should be a search bar".to_string(); } KeyCode::Char(c) => { app.input.push(c); @@ -80,6 +50,8 @@ pub(crate) fn subscribe_state(app: &mut AppSub) -> io::Result { //KeyCode::Left => app.unselect(), KeyCode::Down => app.next(), KeyCode::Up => app.previous(), + KeyCode::Left => app.left(), + KeyCode::Right => app.right(), KeyCode::Esc => { app.unselect(); app.input_mode = InputMode::Normal; @@ -137,8 +109,8 @@ pub(crate) fn subscribe_state(app: &mut AppSub) -> io::Result { let mut subscribe_json: String = "[\n\n".to_string(); for asub in &app.subscription { subscribe_json.push_str(&format!( - "{{ \n\ - \"url\": \"{}\"\n \ + "{{\n \ + \"url\": \"{}\"\n\ }},\n", asub )); @@ -151,32 +123,46 @@ pub(crate) fn subscribe_state(app: &mut AppSub) -> io::Result { // .collect(); let get_list = spider::get_the_key(app.subscription.clone()); if let Ok(list) = get_list { - let mut storge: String = String::new(); - storge.push('['); - storge.push_str("\n\n"); - if !list.is_empty() && !list[0].is_empty() { - //app.subs = list[0].clone(); - app.stateoflist = true; - app.state[app.subsindex].select(Some(0)); - for alist in &list[0] { - let information = spider::Information::new(alist.to_string()); - app.informations[0].push(information.clone()); - storge.push_str(information.get_the_json_node().as_str()); + if !list.is_empty(){ + let mut storge: String = "[\n\n".to_string(); + let mut subs : Vec> =Vec::new(); + let mut information :Vec> = Vec::new(); + let mut state: Vec= Vec::new(); + for lista in list { + let mut ainformation: Vec = Vec::new(); + //let mut asub: Vec = Vec::new(); + storge.push_str("[\n\n"); + if !lista.is_empty() { + for alist in lista { + let inform = spider::Information::new(alist.to_string()); + ainformation.push(inform.clone()); + storge.push_str(&inform.get_the_json_node()); + + } + storge.pop(); + storge.pop(); + storge.push_str("\n ],"); + } + state.push(ListState::default()); + subs.push(ainformation + .iter() + .map(|ainfor| spider::remove_quotation(ainfor.ps.clone())) + .collect()); + information.push(ainformation); + } - app.subs[0] = app - .informations[0] - .iter() - .map(|ainformation| { - spider::remove_quotation(ainformation.ps.clone()) - }) - .collect(); + app.state = state; + app.subs = subs; + app.informations = information; + storge.pop(); + storge.push_str("\n]"); + utils::create_json_file(utils::Save::Storage, storge) + .unwrap_or_else(|err| panic!("err {}", err)); + app.subsindex = 0; + app.state[0].select(Some(0)); + app.stateoflist=true; + } - storge.pop(); - storge.pop(); - storge.push('\n'); - storge.push(']'); - utils::create_json_file(utils::Save::Storage, storge) - .unwrap_or_else(|err| panic!("err {}", err)); } } _ => {} diff --git a/src/utils.rs b/src/utils.rs index ca9955b..af32bfd 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,5 +1,5 @@ use crate::spider::Information; -use serde_json::{Value,json}; +use serde_json::{json, Value}; use std::{ env, fs::{self, File}, @@ -50,7 +50,8 @@ pub fn start_v2core() -> String { Err(_) => { let core = json!({ "v2core":"/usr/bin/v2ray" - }).to_string(); + }) + .to_string(); create_json_file(Save::V2ray, core.clone()).unwrap_or_else(|err| panic!("{}", err)); core } @@ -81,7 +82,7 @@ pub fn get_subs() -> Vec { } subscribes } -pub fn start() -> Vec { +pub fn start() -> Vec> { create_storage_before(); let messages = match get_json(Save::Storage) { Ok(output) => output, @@ -95,23 +96,30 @@ pub fn start() -> Vec { let v: Value = serde_json::from_str(messages.as_str()).unwrap(); let mut index = 0; while v[index] != Value::Null { - let the_url = v[index]["url"].to_string(); - let length = the_url.len(); - let instore = &the_url[1..length - 1]; - informations.push(Information { - urls: instore.to_string(), - func: v[index]["func"].to_string(), - add: v[index]["add"].to_string(), - aid: v[index]["aid"].to_string(), - host: v[index]["host"].to_string(), - id: v[index]["id"].to_string(), - net: v[index]["net"].to_string(), - path: v[index]["path"].to_string(), - port: v[index]["port"].to_string(), - ps: v[index]["ps"].to_string(), - tls: v[index]["tls"].to_string(), - typpe: v[index]["type"].to_string(), - }); + let mut index2 = 0; + let w = v[index].clone(); + let mut information = Vec::new(); + while w[index2] != Value::Null { + let the_url = w[index2]["url"].to_string(); + let length = the_url.len(); + let instore = &the_url[1..length - 1]; + information.push(Information { + urls: instore.to_string(), + func: w[index2]["func"].to_string(), + add: w[index2]["add"].to_string(), + aid: w[index2]["aid"].to_string(), + host: w[index2]["host"].to_string(), + id: w[index2]["id"].to_string(), + net: w[index2]["net"].to_string(), + path: w[index2]["path"].to_string(), + port: w[index2]["port"].to_string(), + ps: w[index2]["ps"].to_string(), + tls: w[index2]["tls"].to_string(), + typpe: w[index2]["type"].to_string(), + }); + index2 += 1; + } + informations.push(information); //let names = v[index]["ps"].to_string(); //start.add_item(remove_quotation(names), url); index += 1;