Skip to content

Commit 93d2133

Browse files
committed
chore: update version to 1.0.11 and implement auto-reset feature for quota segment
1 parent 76b430e commit 93d2133

File tree

13 files changed

+219
-27
lines changed

13 files changed

+219
-27
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ccometixline-88cc"
3-
version = "1.0.10"
3+
version = "1.0.11"
44
edition = "2021"
55
description = "CCometixLine (ccline) - High-performance Claude Code StatusLine tool written in Rust (88Code version)"
66
authors = ["Hobee Liu"]
@@ -36,4 +36,4 @@ path = "src/main.rs"
3636
default = ["tui", "self-update", "dirs", "quota"]
3737
tui = ["ratatui", "crossterm", "ansi_term", "ansi-to-tui", "chrono"]
3838
self-update = ["ureq", "semver", "chrono", "dirs"]
39-
quota = ["ureq", "dirs"]
39+
quota = ["ureq", "dirs", "chrono"]

src/core/segments/quota.rs

Lines changed: 123 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -247,16 +247,105 @@ impl QuotaSegment {
247247
}
248248
}
249249

250-
fn format_reset_info(&self, reset_times: u32, auto_reset: bool) -> String {
251-
if reset_times > 0 {
252-
if auto_reset {
253-
format!("↻ {} AutoReset", reset_times)
254-
} else {
255-
format!("↻ {}", reset_times)
256-
}
250+
fn format_reset_info(&self, reset_times: u32, auto_reset_when_zero: bool, user_auto_reset_enabled: bool) -> String {
251+
let status = if user_auto_reset_enabled {
252+
// 用户在TUI中启用了Auto Reset
253+
"[reset on auto]"
254+
} else if auto_reset_when_zero {
255+
// API返回的auto_reset_when_zero为true
256+
"[reset on zero]"
257257
} else {
258-
String::new()
258+
"[reset off]"
259+
};
260+
format!("↻ {} {}", reset_times, status)
261+
}
262+
263+
/// 检查当前是否在重置时间窗口内
264+
/// - 18:55-18:59:必须剩余2次或更多重置机会才进行重置
265+
/// - 23:55-23:59:只要有重置次数(>=1)就进行重置
266+
fn is_in_reset_window(&self, reset_times: u32) -> bool {
267+
use chrono::{Local, Timelike};
268+
269+
let now = Local::now();
270+
let hour = now.hour();
271+
let minute = now.minute();
272+
273+
// 18:55 - 18:59:需要2次或更多重置机会
274+
if hour == 18 && minute >= 55 && minute <= 59 {
275+
return reset_times >= 2;
276+
}
277+
278+
// 23:55 - 23:59:只要有重置次数就可以
279+
if hour == 23 && minute >= 55 && minute <= 59 {
280+
return reset_times >= 1;
259281
}
282+
283+
false
284+
}
285+
286+
/// 执行重置操作(调用API)
287+
/// 返回重置是否成功
288+
fn perform_reset(&self, api_key: &str, subscription_id: u32) -> bool {
289+
let url = format!("https://www.88code.org/api/reset-credits/{}", subscription_id);
290+
let bearer_token = format!("Bearer {}", api_key);
291+
let debug = env::var("C88_DEBUG").is_ok();
292+
293+
if debug {
294+
eprintln!("[DEBUG] Attempting to reset credits for subscription {}", subscription_id);
295+
}
296+
297+
let result = ureq::post(&url)
298+
.set("accept", "*/*")
299+
.set("content-type", "application/json")
300+
.set("Authorization", &bearer_token)
301+
.timeout(Duration::from_secs(5))
302+
.call();
303+
304+
match result {
305+
Ok(response) => {
306+
if response.status() == 200 {
307+
if debug {
308+
eprintln!("[DEBUG] Reset successful for subscription {}", subscription_id);
309+
}
310+
true
311+
} else {
312+
if debug {
313+
eprintln!("[DEBUG] Reset failed with status {}", response.status());
314+
}
315+
false
316+
}
317+
}
318+
Err(e) => {
319+
if debug {
320+
eprintln!("[DEBUG] Reset error: {}", e);
321+
}
322+
false
323+
}
324+
}
325+
}
326+
327+
/// 检查并执行自动重置(如果需要)
328+
fn check_and_auto_reset(
329+
&self,
330+
api_key: &str,
331+
subscription_id: u32,
332+
reset_times: u32,
333+
auto_reset_enabled: bool,
334+
) -> bool {
335+
if !auto_reset_enabled {
336+
return false;
337+
}
338+
339+
if reset_times == 0 {
340+
return false;
341+
}
342+
343+
if !self.is_in_reset_window(reset_times) {
344+
return false;
345+
}
346+
347+
// 在重置窗口内,执行重置
348+
self.perform_reset(api_key, subscription_id)
260349
}
261350
}
262351

@@ -271,6 +360,19 @@ impl Segment for QuotaSegment {
271360
{
272361
let api_key = self.load_api_key()?;
273362

363+
// 加载配置获取auto_reset_enabled选项
364+
let auto_reset_enabled = if let Ok(config) = crate::config::Config::load() {
365+
config
366+
.segments
367+
.iter()
368+
.find(|s| s.id == SegmentId::Quota)
369+
.and_then(|sc| sc.options.get("auto_reset_enabled"))
370+
.and_then(|v| v.as_bool())
371+
.unwrap_or(false)
372+
} else {
373+
false
374+
};
375+
274376
// 使用静态方法进行端点检测
275377
if let Some((endpoint_url, response)) =
276378
SmartEndpointDetector::detect_endpoint_static(&api_key)
@@ -282,7 +384,19 @@ impl Segment for QuotaSegment {
282384
// 获取重置次数信息
283385
let reset_info = if let Some(sub_id) = response.subscription_id {
284386
if let Some(sub_info) = self.fetch_subscription_info(&api_key, sub_id) {
285-
self.format_reset_info(sub_info.reset_times, sub_info.auto_reset_when_zero)
387+
// 检查并执行自动重置(内部会进行所有必要的检查)
388+
let _ = self.check_and_auto_reset(
389+
&api_key,
390+
sub_id,
391+
sub_info.reset_times,
392+
auto_reset_enabled,
393+
);
394+
395+
self.format_reset_info(
396+
sub_info.reset_times,
397+
sub_info.auto_reset_when_zero,
398+
auto_reset_enabled
399+
)
286400
} else {
287401
String::new()
288402
}

src/ui/app.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -562,9 +562,36 @@ impl App {
562562
}
563563
}
564564
FieldSelection::Options => {
565-
// TODO: Implement options editor
566-
self.status_message =
567-
Some("Options editor not implemented yet".to_string());
565+
// Handle segment-specific options
566+
if let Some(segment) = self.config.segments.get_mut(self.selected_segment) {
567+
match segment.id {
568+
SegmentId::Quota => {
569+
// Toggle auto_reset_enabled for Quota segment
570+
let current_value = segment
571+
.options
572+
.get("auto_reset_enabled")
573+
.and_then(|v| v.as_bool())
574+
.unwrap_or(false);
575+
segment.options.insert(
576+
"auto_reset_enabled".to_string(),
577+
serde_json::Value::Bool(!current_value),
578+
);
579+
self.status_message = Some(format!(
580+
"Auto Reset {}",
581+
if !current_value {
582+
"enabled"
583+
} else {
584+
"disabled"
585+
}
586+
));
587+
self.preview.update_preview(&self.config);
588+
}
589+
_ => {
590+
self.status_message =
591+
Some("No options available for this segment".to_string());
592+
}
593+
}
594+
}
568595
}
569596
}
570597
}

src/ui/components/settings.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -269,10 +269,25 @@ impl SettingsComponent {
269269
),
270270
create_field_line(
271271
FieldSelection::Options,
272-
vec![Span::raw(format!(
273-
"└─ Options: {} items",
274-
segment.options.len()
275-
))],
272+
{
273+
// Show auto_reset_enabled status for Quota segment
274+
if segment.id == SegmentId::Quota {
275+
let auto_reset_enabled = segment
276+
.options
277+
.get("auto_reset_enabled")
278+
.and_then(|v| v.as_bool())
279+
.unwrap_or(false);
280+
vec![Span::raw(format!(
281+
"└─ Auto Reset: {}",
282+
if auto_reset_enabled { "[✓]" } else { "[ ]" }
283+
))]
284+
} else {
285+
vec![Span::raw(format!(
286+
"└─ Options: {} items",
287+
segment.options.len()
288+
))]
289+
}
290+
},
276291
),
277292
];
278293
let text = Text::from(lines);

src/ui/themes/theme_cometix.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ pub fn quota_segment() -> SegmentConfig {
177177
background: None,
178178
},
179179
styles: TextStyleConfig { text_bold: true },
180-
options: HashMap::new(),
180+
options: {
181+
let mut opts = HashMap::new();
182+
opts.insert("auto_reset_enabled".to_string(), serde_json::Value::Bool(false));
183+
opts
184+
},
181185
}
182186
}

src/ui/themes/theme_default.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ pub fn quota_segment() -> SegmentConfig {
177177
background: None,
178178
},
179179
styles: TextStyleConfig::default(),
180-
options: HashMap::new(),
180+
options: {
181+
let mut opts = HashMap::new();
182+
opts.insert("auto_reset_enabled".to_string(), serde_json::Value::Bool(false));
183+
opts
184+
},
181185
}
182186
}

src/ui/themes/theme_gruvbox.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ pub fn quota_segment() -> SegmentConfig {
177177
background: None,
178178
},
179179
styles: TextStyleConfig { text_bold: true },
180-
options: HashMap::new(),
180+
options: {
181+
let mut opts = HashMap::new();
182+
opts.insert("auto_reset_enabled".to_string(), serde_json::Value::Bool(false));
183+
opts
184+
},
181185
}
182186
}

src/ui/themes/theme_minimal.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ pub fn quota_segment() -> SegmentConfig {
177177
background: None,
178178
},
179179
styles: TextStyleConfig::default(),
180-
options: HashMap::new(),
180+
options: {
181+
let mut opts = HashMap::new();
182+
opts.insert("auto_reset_enabled".to_string(), serde_json::Value::Bool(false));
183+
opts
184+
},
181185
}
182186
}

src/ui/themes/theme_nord.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,10 @@ pub fn quota_segment() -> SegmentConfig {
273273
}),
274274
},
275275
styles: TextStyleConfig::default(),
276-
options: HashMap::new(),
276+
options: {
277+
let mut opts = HashMap::new();
278+
opts.insert("auto_reset_enabled".to_string(), serde_json::Value::Bool(false));
279+
opts
280+
},
277281
}
278282
}

src/ui/themes/theme_powerline_dark.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,10 @@ pub fn quota_segment() -> SegmentConfig {
273273
}),
274274
},
275275
styles: TextStyleConfig::default(),
276-
options: HashMap::new(),
276+
options: {
277+
let mut opts = HashMap::new();
278+
opts.insert("auto_reset_enabled".to_string(), serde_json::Value::Bool(false));
279+
opts
280+
},
277281
}
278282
}

0 commit comments

Comments
 (0)