experimental cancel on upload
This commit is contained in:
@@ -4,7 +4,6 @@
|
|||||||
- [ ] File upload multiline description (window)
|
- [ ] File upload multiline description (window)
|
||||||
- [ ] Separate common structures in the common.h
|
- [ ] Separate common structures in the common.h
|
||||||
- [ ] Sorting in the file list
|
- [ ] Sorting in the file list
|
||||||
- [ ] More intuitive navigation between nested groups (by pressing left and right buttons)
|
|
||||||
- [ ] Cancel upload/download
|
- [ ] Cancel upload/download
|
||||||
- [x] Input: fix non-Latin letters
|
- [x] Input: fix non-Latin letters
|
||||||
- [x] Get rid of unsigned integers
|
- [x] Get rid of unsigned integers
|
||||||
@@ -30,6 +29,7 @@
|
|||||||
- [x] UTF-8 support
|
- [x] UTF-8 support
|
||||||
- [ ] Check MD5 sum after download/upload
|
- [ ] Check MD5 sum after download/upload
|
||||||
- [ ] Hotkeys for buttons
|
- [ ] Hotkeys for buttons
|
||||||
|
- [ ] Manipulation by UI-cursor
|
||||||
|
|
||||||
## Fixes:
|
## Fixes:
|
||||||
- [x] Check and fix registration and login
|
- [x] Check and fix registration and login
|
||||||
|
|||||||
+56
-2
@@ -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);
|
fl_item_t *f_selected = &(f_args->f_selected);
|
||||||
static int32_t it_count = 0;
|
static int32_t it_count = 0;
|
||||||
static size_t it_interval = 0;
|
static size_t it_interval = 0;
|
||||||
|
|
||||||
if (it_interval == 0) {
|
if (it_interval == 0) {
|
||||||
it_interval = (f_selected->size / INBUFSIZE / 100) * 5; /* every 1% */
|
it_interval = (f_selected->size / INBUFSIZE / 100) * 5; /* every 1% */
|
||||||
if (it_interval == 0)
|
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) {
|
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 = malloc(sizeof(p_file_t));
|
||||||
q_args->file->path = malloc(strlen(dpath) + strlen(fname) + 2);
|
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);
|
sprintf(q_args->file->path, "%s/%s", dpath, fname);
|
||||||
int fd = open(q_args->file->path, O_RDONLY);
|
int fd = open(q_args->file->path, O_RDONLY);
|
||||||
if (fd == -1) {
|
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) {
|
int32_t file_upload(query_args_t *q_args) {
|
||||||
static int32_t it_count = 0;
|
static int32_t it_count = 0;
|
||||||
static size_t it_interval = 0;
|
static size_t it_interval = 0;
|
||||||
|
static int package_rest = 0;
|
||||||
|
int send_len = q_args->buf_used;
|
||||||
if (it_interval == 0) {
|
if (it_interval == 0) {
|
||||||
it_interval = (q_args->file->size / INBUFSIZE / 100) * 5; /* every 1% */
|
it_interval = (q_args->file->size / INBUFSIZE / 100) * 5; /* every 1% */
|
||||||
if (it_interval == 0)
|
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;
|
(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_pgb_ui_t *pb = (w_pgb_ui_t *)q_args->progress_bar;
|
||||||
w_dialogue_t *d = (w_dialogue_t *)q_args->active_dialogue;
|
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) {
|
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) {
|
if (q_args->buf_used != wlen) {
|
||||||
/* TODO: ошибка */
|
/* TODO: ошибка */
|
||||||
|
/* reset function before exit */
|
||||||
|
it_count = 0;
|
||||||
|
it_interval = 0;
|
||||||
|
package_rest = 0;
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
it_count++;
|
it_count++;
|
||||||
@@ -212,13 +236,43 @@ int32_t file_upload(query_args_t *q_args) {
|
|||||||
pb->procent = progress;
|
pb->procent = progress;
|
||||||
d->needs_update = true;
|
d->needs_update = true;
|
||||||
}
|
}
|
||||||
|
q_args->file->rest -= wlen;
|
||||||
|
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[0] = 0;
|
||||||
q_args->buf_used = 0;
|
q_args->buf_used = 0;
|
||||||
q_args->file->rest -= wlen;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
/* reset function before exit */
|
||||||
it_count = 0;
|
it_count = 0;
|
||||||
it_interval = 0;
|
it_interval = 0;
|
||||||
|
package_rest = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#ifndef FILE_PROCESSOR_H
|
#ifndef FILE_PROCESSOR_H
|
||||||
#define FILE_PROCESSOR_H
|
#define FILE_PROCESSOR_H
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
void file_list(file_args_t *f_args, query_args_t *q_args);
|
void file_list(file_args_t *f_args, query_args_t *q_args);
|
||||||
|
|||||||
+15
-6
@@ -17,6 +17,7 @@
|
|||||||
#define DIALOGUE_TITLE 64
|
#define DIALOGUE_TITLE 64
|
||||||
#define DIALOGUE_TEXT 4096
|
#define DIALOGUE_TEXT 4096
|
||||||
#define INPUT_TEXT DIALOGUE_TITLE
|
#define INPUT_TEXT DIALOGUE_TITLE
|
||||||
|
#define PACKAGE_SIZE INBUFSIZE * 10
|
||||||
|
|
||||||
typedef struct params {
|
typedef struct params {
|
||||||
unsigned short port;
|
unsigned short port;
|
||||||
@@ -59,12 +60,20 @@ enum state {
|
|||||||
WAIT_CLIENT,
|
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 {
|
typedef struct p_file {
|
||||||
char *name;
|
char *name;
|
||||||
char *path;
|
char *path;
|
||||||
char *description;
|
char *description;
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t rest;
|
size_t rest;
|
||||||
|
enum package_signal signal;
|
||||||
int fd;
|
int fd;
|
||||||
} p_file_t;
|
} p_file_t;
|
||||||
|
|
||||||
@@ -85,18 +94,18 @@ typedef struct file_args {
|
|||||||
|
|
||||||
enum main_window_type {
|
enum main_window_type {
|
||||||
mw_fl_server, /* file list on the server */
|
mw_fl_server, /* file list on the server */
|
||||||
mw_fl_local, /* local file list */
|
mw_fl_local, /* local file list */
|
||||||
mw_f_desc, /* file description */
|
mw_f_desc, /* file description */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (draw_f_t) (void *fui) ;
|
typedef void(draw_f_t)(void *fui);
|
||||||
|
|
||||||
typedef struct main_window {
|
typedef struct main_window {
|
||||||
enum main_window_type type;
|
enum main_window_type type;
|
||||||
void *ui; /* structure which describes window UI */
|
void *ui; /* structure which describes window UI */
|
||||||
int32_t (*cb_b_press) (void *app, void *args); /* callback on button press */
|
int32_t (*cb_b_press)(void *app, void *args); /* callback on button press */
|
||||||
void (*cb_ui_refresh) (void *app); /* refresh callback */
|
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;
|
draw_f_t *draw;
|
||||||
struct action_key *b_keys;
|
struct action_key *b_keys;
|
||||||
int32_t b_keys_len;
|
int32_t b_keys_len;
|
||||||
|
|||||||
+17
-7
@@ -1,11 +1,17 @@
|
|||||||
#include "group.h"
|
#include "group.h"
|
||||||
#include <widget.h>
|
|
||||||
#include <ncursesw/ncurses.h>
|
#include <ncursesw/ncurses.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <widget.h>
|
||||||
|
|
||||||
void dwn_pr_modal_cb(w_cb_args_t *args) {
|
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) {
|
w_dialogue_t *m_load_pr_init(app_t *app, bool is_upload) {
|
||||||
@@ -17,18 +23,22 @@ w_dialogue_t *m_load_pr_init(app_t *app, bool is_upload) {
|
|||||||
|
|
||||||
char text[256];
|
char text[256];
|
||||||
sprintf(text, "%s file: %s", is_upload ? "Uploading" : "Downloading",
|
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[] = {
|
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;
|
app->modal.w.parent_win = &app->win;
|
||||||
w_dialogue_init(&(app->modal), is_upload ? "Upload" : "Download", text,
|
w_dialogue_init(&(app->modal), is_upload ? "Upload" : "Download", text,
|
||||||
&(app->coordinates));
|
&(app->coordinates));
|
||||||
w_dialogue_t *d = &(app->modal);
|
w_dialogue_t *d = &(app->modal);
|
||||||
|
|
||||||
d->w.callback = dwn_pr_modal_cb;
|
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_content = w_group_init(&(d->win), &(d->w), content, &(d->id_map),
|
||||||
d->g_action = w_group_init(&(d->win), &(d->w), actions, &(d->id_map), horizontal, g_action);
|
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->progress_bar = d->g_content->elements[0].element;
|
||||||
app->query_args->active_dialogue = d;
|
app->query_args->active_dialogue = d;
|
||||||
|
|||||||
+16
-5
@@ -45,6 +45,13 @@ int32_t process_user_input(app_t *app, w_cb_args_t *d_args);
|
|||||||
app_destroy(app, exit_code); \
|
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) {
|
void query_loop(app_t *app) {
|
||||||
query_args_t *query_args = app->query_args;
|
query_args_t *query_args = app->query_args;
|
||||||
fd_set readfds;
|
fd_set readfds;
|
||||||
@@ -183,11 +190,7 @@ int process_query(app_t *app) {
|
|||||||
if (!file_upload_start(query_args)) {
|
if (!file_upload_start(query_args)) {
|
||||||
query_args->state = S_UPLOAD_FILE;
|
query_args->state = S_UPLOAD_FILE;
|
||||||
} else {
|
} else {
|
||||||
if (app->query_args->file != NULL) {
|
FILE_CLEAN(app);
|
||||||
FREE_MLC(app->query_args->file->name);
|
|
||||||
FREE_MLC(app->query_args->file->path)
|
|
||||||
FREE_MLC(app->query_args->file);
|
|
||||||
}
|
|
||||||
query_args->state = WAIT_CLIENT;
|
query_args->state = WAIT_CLIENT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -198,6 +201,14 @@ int process_query(app_t *app) {
|
|||||||
query_args->state = S_UPLOAD_SERVER_FINISHES;
|
query_args->state = S_UPLOAD_SERVER_FINISHES;
|
||||||
} else if (res == -1) {
|
} else if (res == -1) {
|
||||||
/* TODO: Error */
|
/* 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;
|
break;
|
||||||
case S_UPLOAD_SERVER_FINISHES:
|
case S_UPLOAD_SERVER_FINISHES:
|
||||||
|
|||||||
+5
-11
@@ -136,18 +136,12 @@ void w_dialogue_callback_default(w_cb_args_t *args) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KEY_UP:
|
case KEY_UP:
|
||||||
if (d->active_el->g_type == g_content &&
|
decr_active_id(d);
|
||||||
d->g_content->direction == vertical) {
|
args->resp_data.code = cbrc_none;
|
||||||
decr_active_id(d);
|
|
||||||
args->resp_data.code = cbrc_none;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case KEY_DOWN:
|
case KEY_DOWN:
|
||||||
if (d->active_el->g_type == g_content &&
|
incr_active_id(d);
|
||||||
d->g_content->direction == vertical) {
|
args->resp_data.code = cbrc_none;
|
||||||
incr_active_id(d);
|
|
||||||
args->resp_data.code = cbrc_none;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* run callback function */
|
/* run callback function */
|
||||||
@@ -329,7 +323,7 @@ void w_dialogue_destroy(w_dialogue_t *d, void *_app) {
|
|||||||
}
|
}
|
||||||
delwin(d->win);
|
delwin(d->win);
|
||||||
d->win = NULL;
|
d->win = NULL;
|
||||||
d->is_initiated = 0;
|
d->is_initiated = false;
|
||||||
d->needs_destroy = false;
|
d->needs_destroy = false;
|
||||||
app->active_callback = (w_cb_t)app->main_ui.cb_b_press;
|
app->active_callback = (w_cb_t)app->main_ui.cb_b_press;
|
||||||
app->query_args->active_dialogue = NULL;
|
app->query_args->active_dialogue = NULL;
|
||||||
|
|||||||
+7
-7
@@ -5,8 +5,8 @@
|
|||||||
#define W_INPUT_H
|
#define W_INPUT_H
|
||||||
|
|
||||||
#include "../main.h"
|
#include "../main.h"
|
||||||
#include <widget_core.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <widget_core.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
w_t w;
|
w_t w;
|
||||||
@@ -18,11 +18,11 @@ typedef struct {
|
|||||||
bool is_hidden;
|
bool is_hidden;
|
||||||
} w_input_t;
|
} w_input_t;
|
||||||
|
|
||||||
bool w_input_default_key_action(w_cb_args_t *args);
|
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,
|
w_input_t *w_input_init(WINDOW **win, w_t *w_parent, char *label, int32_t size,
|
||||||
int32_t size, int32_t is_hidden_value);
|
int32_t is_hidden_value);
|
||||||
int32_t w_input_draw(w_input_t *input, int32_t active_id);
|
int32_t w_input_draw(w_input_t *input, int32_t active_id);
|
||||||
void w_input_destroy(w_input_t *input);
|
void w_input_destroy(w_input_t *input);
|
||||||
char *w_input_get_value(w_input_t *input);
|
char *w_input_get_value(w_input_t *input);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -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()
|
||||||
Reference in New Issue
Block a user