feat: animated connecting icon
This commit is contained in:
parent
8c0b65220a
commit
9e37d72071
59
main.jai
59
main.jai
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
// Custom constants
|
// Custom constants
|
||||||
TIMER_PROCESS_CHECK :: 1;
|
TIMER_PROCESS_CHECK :: 1;
|
||||||
|
TIMER_ANIMATION :: 2;
|
||||||
|
|
||||||
IDI_APPLICATION :: cast(*u16) 32512;
|
IDI_APPLICATION :: cast(*u16) 32512;
|
||||||
IDI_SHIELD :: cast(*u16) 32518;
|
IDI_SHIELD :: cast(*u16) 32518;
|
||||||
@ -28,6 +29,12 @@ App_State :: struct {
|
|||||||
|
|
||||||
icon_running: HICON;
|
icon_running: HICON;
|
||||||
icon_stopped: HICON;
|
icon_stopped: HICON;
|
||||||
|
|
||||||
|
is_connecting: bool;
|
||||||
|
connecting_ticks: int;
|
||||||
|
is_updating: bool;
|
||||||
|
animation_frame: int;
|
||||||
|
icon_frames: [4] HICON;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom log print sending logs to OutputDebugStringW
|
// Custom log print sending logs to OutputDebugStringW
|
||||||
@ -133,7 +140,13 @@ update_tray :: (app: *App_State) {
|
|||||||
nid.uID = 1;
|
nid.uID = 1;
|
||||||
nid.uFlags = NIF_ICON | NIF_TIP;
|
nid.uFlags = NIF_ICON | NIF_TIP;
|
||||||
|
|
||||||
if app.singbox_running {
|
if app.is_connecting {
|
||||||
|
nid.hIcon = app.icon_frames[app.animation_frame];
|
||||||
|
set_tray_tip(*nid, "Sing-box: Connecting...");
|
||||||
|
} else if app.is_updating {
|
||||||
|
nid.hIcon = app.icon_frames[app.animation_frame];
|
||||||
|
set_tray_tip(*nid, "Sing-box: Updating Config...");
|
||||||
|
} else if app.singbox_running {
|
||||||
nid.hIcon = app.icon_running;
|
nid.hIcon = app.icon_running;
|
||||||
set_tray_tip(*nid, "Sing-box: Running");
|
set_tray_tip(*nid, "Sing-box: Running");
|
||||||
} else {
|
} else {
|
||||||
@ -218,6 +231,11 @@ start_singbox :: (app: *App_State) -> bool {
|
|||||||
app.singbox_job_handle = job;
|
app.singbox_job_handle = job;
|
||||||
app.singbox_running = true;
|
app.singbox_running = true;
|
||||||
|
|
||||||
|
app.is_connecting = true;
|
||||||
|
app.connecting_ticks = 0;
|
||||||
|
app.animation_frame = 0;
|
||||||
|
SetTimer(app.hwnd, TIMER_ANIMATION, 250, null);
|
||||||
|
|
||||||
if app.use_system_proxy {
|
if app.use_system_proxy {
|
||||||
set_windows_system_proxy(true, tprint("127.0.0.1:%", app.port));
|
set_windows_system_proxy(true, tprint("127.0.0.1:%", app.port));
|
||||||
log_print("System proxy enabled on port %.\n", app.port);
|
log_print("System proxy enabled on port %.\n", app.port);
|
||||||
@ -229,6 +247,9 @@ start_singbox :: (app: *App_State) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
stop_singbox :: (app: *App_State) {
|
stop_singbox :: (app: *App_State) {
|
||||||
|
app.is_connecting = false;
|
||||||
|
KillTimer(app.hwnd, TIMER_ANIMATION);
|
||||||
|
|
||||||
if !app.singbox_running return;
|
if !app.singbox_running return;
|
||||||
|
|
||||||
TerminateProcess(app.singbox_process_handle, 0);
|
TerminateProcess(app.singbox_process_handle, 0);
|
||||||
@ -279,7 +300,15 @@ check_process_status :: (app: *App_State) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trigger_immediate_update :: (app: *App_State) {
|
trigger_immediate_update :: (app: *App_State) {
|
||||||
|
app.is_updating = true;
|
||||||
|
app.animation_frame = 0;
|
||||||
|
SetTimer(app.hwnd, TIMER_ANIMATION, 150, null);
|
||||||
|
update_tray(app);
|
||||||
|
|
||||||
changed, success, err_msg := perform_update();
|
changed, success, err_msg := perform_update();
|
||||||
|
|
||||||
|
app.is_updating = false;
|
||||||
|
|
||||||
if success {
|
if success {
|
||||||
if changed {
|
if changed {
|
||||||
log_print("Config updated, restarting Sing-box...\n");
|
log_print("Config updated, restarting Sing-box...\n");
|
||||||
@ -293,10 +322,15 @@ trigger_immediate_update :: (app: *App_State) {
|
|||||||
} else {
|
} else {
|
||||||
if !app.singbox_running {
|
if !app.singbox_running {
|
||||||
start_singbox(app);
|
start_singbox(app);
|
||||||
|
} else {
|
||||||
|
KillTimer(app.hwnd, TIMER_ANIMATION);
|
||||||
|
update_tray(app);
|
||||||
}
|
}
|
||||||
MessageBoxW(app.hwnd, utf8_to_wide("Configuration is already up-to-date."), utf8_to_wide("Sing-box Tray"), MB_ICONINFORMATION);
|
MessageBoxW(app.hwnd, utf8_to_wide("Configuration is already up-to-date."), utf8_to_wide("Sing-box Tray"), MB_ICONINFORMATION);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
KillTimer(app.hwnd, TIMER_ANIMATION);
|
||||||
|
update_tray(app);
|
||||||
msg := tprint("Failed to download configuration.\nError: %", err_msg);
|
msg := tprint("Failed to download configuration.\nError: %", err_msg);
|
||||||
MessageBoxW(app.hwnd, utf8_to_wide(msg), utf8_to_wide("Sing-box Tray"), MB_ICONERROR);
|
MessageBoxW(app.hwnd, utf8_to_wide(msg), utf8_to_wide("Sing-box Tray"), MB_ICONERROR);
|
||||||
}
|
}
|
||||||
@ -464,6 +498,22 @@ app_wnd_proc :: (hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESUL
|
|||||||
case WM_TIMER; {
|
case WM_TIMER; {
|
||||||
if wparam == TIMER_PROCESS_CHECK {
|
if wparam == TIMER_PROCESS_CHECK {
|
||||||
check_process_status(app);
|
check_process_status(app);
|
||||||
|
} else if wparam == TIMER_ANIMATION {
|
||||||
|
if app.is_connecting {
|
||||||
|
app.connecting_ticks += 1;
|
||||||
|
app.animation_frame = (app.animation_frame + 1) % 4;
|
||||||
|
update_tray(app);
|
||||||
|
|
||||||
|
// Stop connecting animation after 12 ticks (3 seconds at 250ms)
|
||||||
|
if app.connecting_ticks >= 12 {
|
||||||
|
app.is_connecting = false;
|
||||||
|
KillTimer(hwnd, TIMER_ANIMATION);
|
||||||
|
update_tray(app);
|
||||||
|
}
|
||||||
|
} else if app.is_updating {
|
||||||
|
app.animation_frame = (app.animation_frame + 1) % 4;
|
||||||
|
update_tray(app);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -504,6 +554,10 @@ main :: () {
|
|||||||
app_state: App_State;
|
app_state: App_State;
|
||||||
app_state.icon_running = load_stock_icon(SIID_WORLD);
|
app_state.icon_running = load_stock_icon(SIID_WORLD);
|
||||||
app_state.icon_stopped = load_stock_icon(SIID_ERROR);
|
app_state.icon_stopped = load_stock_icon(SIID_ERROR);
|
||||||
|
app_state.icon_frames[0] = load_stock_icon(SIID_SERVER);
|
||||||
|
app_state.icon_frames[1] = load_stock_icon(SIID_DRIVENET);
|
||||||
|
app_state.icon_frames[2] = load_stock_icon(SIID_WORLD);
|
||||||
|
app_state.icon_frames[3] = load_stock_icon(SIID_INTERNET);
|
||||||
|
|
||||||
hwnd := CreateWindowExW(
|
hwnd := CreateWindowExW(
|
||||||
0,
|
0,
|
||||||
@ -593,4 +647,7 @@ main :: () {
|
|||||||
|
|
||||||
if app_state.icon_running DestroyIcon(app_state.icon_running);
|
if app_state.icon_running DestroyIcon(app_state.icon_running);
|
||||||
if app_state.icon_stopped DestroyIcon(app_state.icon_stopped);
|
if app_state.icon_stopped DestroyIcon(app_state.icon_stopped);
|
||||||
|
for app_state.icon_frames {
|
||||||
|
if it DestroyIcon(it);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -207,8 +207,11 @@ SHSTOCKICONINFO :: struct {
|
|||||||
szPath: [260] u16;
|
szPath: [260] u16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SIID_DRIVENET :: 9;
|
||||||
SIID_WORLD :: 13;
|
SIID_WORLD :: 13;
|
||||||
|
SIID_SERVER :: 15;
|
||||||
SIID_ERROR :: 80;
|
SIID_ERROR :: 80;
|
||||||
|
SIID_INTERNET :: 104;
|
||||||
|
|
||||||
SHGSI_ICON :: 0x00000100;
|
SHGSI_ICON :: 0x00000100;
|
||||||
SHGSI_SMALLICON :: 0x00000001;
|
SHGSI_SMALLICON :: 0x00000001;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user