experimental cancel on upload

This commit is contained in:
2026-05-18 18:34:40 +03:00
parent 1c4a68cfa4
commit cc6039b974
9 changed files with 131 additions and 39 deletions
+1 -1
View File
@@ -4,7 +4,6 @@
- [ ] File upload multiline description (window)
- [ ] Separate common structures in the common.h
- [ ] Sorting in the file list
- [ ] More intuitive navigation between nested groups (by pressing left and right buttons)
- [ ] Cancel upload/download
- [x] Input: fix non-Latin letters
- [x] Get rid of unsigned integers
@@ -30,6 +29,7 @@
- [x] UTF-8 support
- [ ] Check MD5 sum after download/upload
- [ ] Hotkeys for buttons
- [ ] Manipulation by UI-cursor
## Fixes:
- [x] Check and fix registration and login
+59 -5
View File
@@ -110,6 +110,7 @@ void file_download(file_args_t *f_args, query_args_t *q_args) {
fl_item_t *f_selected = &(f_args->f_selected);
static int32_t it_count = 0;
static size_t it_interval = 0;
if (it_interval == 0) {
it_interval = (f_selected->size / INBUFSIZE / 100) * 5; /* every 1% */
if (it_interval == 0)
@@ -161,6 +162,7 @@ void file_download(file_args_t *f_args, query_args_t *q_args) {
int32_t file_upload_open(char *dpath, char *fname, query_args_t *q_args) {
q_args->file = malloc(sizeof(p_file_t));
q_args->file->path = malloc(strlen(dpath) + strlen(fname) + 2);
q_args->file->signal = sig_continue;
sprintf(q_args->file->path, "%s/%s", dpath, fname);
int fd = open(q_args->file->path, O_RDONLY);
if (fd == -1) {
@@ -192,6 +194,8 @@ int32_t file_upload_start(query_args_t *q_args) {
int32_t file_upload(query_args_t *q_args) {
static int32_t it_count = 0;
static size_t it_interval = 0;
static int package_rest = 0;
int send_len = q_args->buf_used;
if (it_interval == 0) {
it_interval = (q_args->file->size / INBUFSIZE / 100) * 5; /* every 1% */
if (it_interval == 0)
@@ -201,10 +205,30 @@ int32_t file_upload(query_args_t *q_args) {
(q_args->file->size - q_args->file->rest) * 100 / q_args->file->size;
w_pgb_ui_t *pb = (w_pgb_ui_t *)q_args->progress_bar;
w_dialogue_t *d = (w_dialogue_t *)q_args->active_dialogue;
if (package_rest == 0) {
if (q_args->file->signal == sig_cancel) {
/* reset function before exit */
it_count = 0;
it_interval = 0;
return -2;
}
package_rest = PACKAGE_SIZE;
s_file_pd_t fpd = {.signal = q_args->file->signal,
.package_size = package_rest};
write(q_args->sd, &fpd, sizeof(s_file_pd_t));
} else if (package_rest < send_len) {
send_len = package_rest;
}
if (q_args->buf_used > 0) {
int wlen = write(q_args->sd, q_args->buf, q_args->buf_used);
int wlen = write(q_args->sd, q_args->buf, send_len);
if (q_args->buf_used != wlen) {
/* TODO: ошибка */
/* reset function before exit */
it_count = 0;
it_interval = 0;
package_rest = 0;
return -1;
} else {
it_count++;
@@ -212,13 +236,43 @@ int32_t file_upload(query_args_t *q_args) {
pb->procent = progress;
d->needs_update = true;
}
q_args->buf[0] = 0;
q_args->buf_used = 0;
q_args->file->rest -= wlen;
}
} else {
package_rest -= wlen;
if (package_rest == 0) {
if (q_args->file->signal == sig_cancel) {
/* reset function before exit */
it_count = 0;
it_interval = 0;
return -2;
}
package_rest = PACKAGE_SIZE;
s_file_pd_t fpd = {.signal = q_args->file->signal,
.package_size = package_rest};
write(q_args->sd, &fpd, sizeof(s_file_pd_t));
/* send the rest */
if (q_args->buf_used > send_len) {
wlen = write(q_args->sd, q_args->buf + send_len,
q_args->buf_used - send_len);
if (q_args->buf_used != wlen) {
/* TODO: ошибка */
/* reset function before exit */
it_count = 0;
it_interval = 0;
package_rest = 0;
return -1;
}
q_args->file->rest -= wlen;
package_rest -= wlen;
}
}
q_args->buf[0] = 0;
q_args->buf_used = 0;
}
} else {
/* reset function before exit */
it_count = 0;
it_interval = 0;
package_rest = 0;
return 1;
}
return 0;
+1
View File
@@ -3,6 +3,7 @@
#ifndef FILE_PROCESSOR_H
#define FILE_PROCESSOR_H
#include "main.h"
void file_list(file_args_t *f_args, query_args_t *q_args);
+10 -1
View File
@@ -17,6 +17,7 @@
#define DIALOGUE_TITLE 64
#define DIALOGUE_TEXT 4096
#define INPUT_TEXT DIALOGUE_TITLE
#define PACKAGE_SIZE INBUFSIZE * 10
typedef struct params {
unsigned short port;
@@ -59,12 +60,20 @@ enum state {
WAIT_CLIENT,
};
enum package_signal { sig_continue, sig_cancel, sig_finish, sig_pause };
typedef struct {
enum package_signal signal;
size_t package_size;
} s_file_pd_t; /* file package descriptor */
typedef struct p_file {
char *name;
char *path;
char *description;
size_t size;
size_t rest;
enum package_signal signal;
int fd;
} p_file_t;
@@ -96,7 +105,7 @@ typedef struct main_window {
void *ui; /* structure which describes window UI */
int32_t (*cb_b_press)(void *app, void *args); /* callback on button press */
void (*cb_ui_refresh)(void *app); /* refresh callback */
void (*reset) (void *app); /* reset state of the window */
void (*reset)(void *app); /* function to reset the state of the window */
draw_f_t *draw;
struct action_key *b_keys;
int32_t b_keys_len;
+16 -6
View File
@@ -1,11 +1,17 @@
#include "group.h"
#include <widget.h>
#include <ncursesw/ncurses.h>
#include <stdint.h>
#include <stdio.h>
#include <widget.h>
void dwn_pr_modal_cb(w_cb_args_t *args) {
/* TODO: cancel action */
/* only cancel action */
int32_t key = *((int32_t *)args->data);
if (key != '\n') {
return;
}
app_t *app = args->app;
app->query_args->file->signal = sig_cancel;
}
w_dialogue_t *m_load_pr_init(app_t *app, bool is_upload) {
@@ -17,9 +23,11 @@ w_dialogue_t *m_load_pr_init(app_t *app, bool is_upload) {
char text[256];
sprintf(text, "%s file: %s", is_upload ? "Uploading" : "Downloading",
is_upload ? app->query_args->file->name : app->file_args->f_selected.name);
is_upload ? app->query_args->file->name
: app->file_args->f_selected.name);
w_group_el_init_t actions[] = {
{.type = w_button, .label = "Cancel", .is_default = true, .val.num = 1}, {.type = w_end}};
{.type = w_button, .label = "Cancel", .is_default = true, .val.num = 1},
{.type = w_end}};
app->modal.w.parent_win = &app->win;
w_dialogue_init(&(app->modal), is_upload ? "Upload" : "Download", text,
@@ -27,8 +35,10 @@ w_dialogue_t *m_load_pr_init(app_t *app, bool is_upload) {
w_dialogue_t *d = &(app->modal);
d->w.callback = dwn_pr_modal_cb;
d->g_content = w_group_init(&(d->win), &(d->w), content, &(d->id_map), horizontal, g_content);
d->g_action = w_group_init(&(d->win), &(d->w), actions, &(d->id_map), horizontal, g_action);
d->g_content = w_group_init(&(d->win), &(d->w), content, &(d->id_map),
horizontal, g_content);
d->g_action = w_group_init(&(d->win), &(d->w), actions, &(d->id_map),
horizontal, g_action);
app->query_args->progress_bar = d->g_content->elements[0].element;
app->query_args->active_dialogue = d;
+16 -5
View File
@@ -45,6 +45,13 @@ int32_t process_user_input(app_t *app, w_cb_args_t *d_args);
app_destroy(app, exit_code); \
}
#define FILE_CLEAN(app) \
if (app->query_args->file != NULL) { \
FREE_MLC(app->query_args->file->name); \
FREE_MLC(app->query_args->file->path); \
FREE_MLC(app->query_args->file); \
}
void query_loop(app_t *app) {
query_args_t *query_args = app->query_args;
fd_set readfds;
@@ -183,11 +190,7 @@ int process_query(app_t *app) {
if (!file_upload_start(query_args)) {
query_args->state = S_UPLOAD_FILE;
} else {
if (app->query_args->file != NULL) {
FREE_MLC(app->query_args->file->name);
FREE_MLC(app->query_args->file->path)
FREE_MLC(app->query_args->file);
}
FILE_CLEAN(app);
query_args->state = WAIT_CLIENT;
}
break;
@@ -198,6 +201,14 @@ int process_query(app_t *app) {
query_args->state = S_UPLOAD_SERVER_FINISHES;
} else if (res == -1) {
/* TODO: Error */
} else if (res == -2) {
/* cancel case */
w_notification("Alert", dc_alert, "File %s didn't upload!",
query_args->file->name);
FILE_CLEAN(app);
w_dialogue_t *d = &(app->modal);
d->needs_destroy = true;
query_args->state = WAIT_CLIENT;
}
break;
case S_UPLOAD_SERVER_FINISHES:
+1 -7
View File
@@ -136,18 +136,12 @@ void w_dialogue_callback_default(w_cb_args_t *args) {
}
break;
case KEY_UP:
if (d->active_el->g_type == g_content &&
d->g_content->direction == vertical) {
decr_active_id(d);
args->resp_data.code = cbrc_none;
}
break;
case KEY_DOWN:
if (d->active_el->g_type == g_content &&
d->g_content->direction == vertical) {
incr_active_id(d);
args->resp_data.code = cbrc_none;
}
break;
default:
/* run callback function */
@@ -329,7 +323,7 @@ void w_dialogue_destroy(w_dialogue_t *d, void *_app) {
}
delwin(d->win);
d->win = NULL;
d->is_initiated = 0;
d->is_initiated = false;
d->needs_destroy = false;
app->active_callback = (w_cb_t)app->main_ui.cb_b_press;
app->query_args->active_dialogue = NULL;
+3 -3
View File
@@ -5,8 +5,8 @@
#define W_INPUT_H
#include "../main.h"
#include <widget_core.h>
#include <stdint.h>
#include <widget_core.h>
typedef struct {
w_t w;
@@ -19,8 +19,8 @@ typedef struct {
} w_input_t;
bool w_input_default_key_action(w_cb_args_t *args);
w_input_t *w_input_init(WINDOW **win, w_t *w_parent, char *label,
int32_t size, int32_t is_hidden_value);
w_input_t *w_input_init(WINDOW **win, w_t *w_parent, char *label, int32_t size,
int32_t is_hidden_value);
int32_t w_input_draw(w_input_t *input, int32_t active_id);
void w_input_destroy(w_input_t *input);
char *w_input_get_value(w_input_t *input);
+13
View File
@@ -0,0 +1,13 @@
project("My Awesome Tested Project" C)
cmake_minimum_required(VERSION 3.0) # Let's tell it a bit about our environment
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) # We declare a variable to select what to build
set (TARGET_GROUP production CACHE STRING "What Should I Build?") # Modules that exist in both our release and our unit tests, are added now
add_subdirectory(src) if(TARGET_GROUP STREQUAL release) # If we had any files that ONLY were compiled into our release, for example startup code,
# it's really handy to put it here.
elseif(TARGET_GROUP STREQUAL test) # Our tests need to let CTest know we're running tests
include(CTest) # It also needs to understand we have code in source and test directories
add_subdirectory(unity)
add_subdirectory(test)
else()
message(FATAL_ERROR "I don't know the TARGET_GROUP you gave me!")
endif()