diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index b6c6b57..75d0e83 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -50,7 +50,7 @@ jobs: - name: Install build tools run: | sudo apt-get update -y - sudo apt-get install -y cmake pkg-config libgtk-3-dev libcurl4-openssl-dev libjson-c-dev + sudo apt-get install -y cmake pkg-config libgtk-3-dev libcurl4-openssl-dev libjson-c-dev libnotify-dev - name: Set reusable strings # Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file. diff --git a/client-frontend/dragon-tea/CMakeLists.txt b/client-frontend/dragon-tea/CMakeLists.txt index 3996b45..8f2aaeb 100644 --- a/client-frontend/dragon-tea/CMakeLists.txt +++ b/client-frontend/dragon-tea/CMakeLists.txt @@ -8,6 +8,7 @@ pkg_check_modules(gtk3ui REQUIRED gtk+-3.0) pkg_check_modules(libcurl REQUIRED libcurl) pkg_check_modules(json REQUIRED json-c) pkg_check_modules(gthread REQUIRED gthread-2.0) +pkg_check_modules(libnotify REQUIRED libnotify) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) @@ -48,10 +49,12 @@ target_sources(dragontea PUBLIC ${DRAGONTEA_SOURCES}) target_include_directories( dragontea PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include/" ${gtk3ui_INCLUDE_DIRS} - ${gthread_INCLUDE_DIRS} ${libcurl_INCLUDE_DIRS} ${json_INCLUDE_DIRS}) + ${gthread_INCLUDE_DIRS} ${libcurl_INCLUDE_DIRS} ${json_INCLUDE_DIRS} + ${libnotify_INCLUDE_DIRS}) -target_link_libraries(dragontea ${gtk3ui_LIBRARIES} ${libcurl_LIBRARIES} - ${json_LIBRARIES} ${gthread_LIBRARIES}) +target_link_libraries( + dragontea ${gtk3ui_LIBRARIES} ${libcurl_LIBRARIES} ${json_LIBRARIES} + ${gthread_LIBRARIES} ${libnotify_LIBRARIES}) target_compile_definitions(dragontea PUBLIC DRAGON_TEA_VERSION="${DRAGON_TEA_VERSION}") diff --git a/client-frontend/dragon-tea/builtin/server4.url b/client-frontend/dragon-tea/builtin/server4.url new file mode 100644 index 0000000..e9dd127 --- /dev/null +++ b/client-frontend/dragon-tea/builtin/server4.url @@ -0,0 +1 @@ +https://dragontea.farboxgames.repl.co/ diff --git a/client-frontend/dragon-tea/include/tea.h b/client-frontend/dragon-tea/include/tea.h index f6e6f1b..e02e10c 100644 --- a/client-frontend/dragon-tea/include/tea.h +++ b/client-frontend/dragon-tea/include/tea.h @@ -27,6 +27,7 @@ typedef DWORD uid_t; #include #include #include +#include #include "tea_structs.h" #include "tea_api.h" @@ -58,11 +59,13 @@ typedef DWORD uid_t; extern struct tea_net_stats net_stats; extern struct tea_server_info cur_server; -extern struct tea_settings app_settings; +extern struct tea_settings env; extern struct tea_app_widgets widgets; void tea_init(); +void tea_free(); + const char *tea_version(); // User Interface Implementation @@ -87,6 +90,8 @@ int tea_get_server_id(const char *serverURI); int tea_get_builtin_server_list(char list[3][64]); +void tea_read_urls(struct tea_server_urls *wrData); + void tea_load(); void tea_save(); diff --git a/client-frontend/dragon-tea/include/tea_api.h b/client-frontend/dragon-tea/include/tea_api.h index b2943e7..fd4ea11 100644 --- a/client-frontend/dragon-tea/include/tea_api.h +++ b/client-frontend/dragon-tea/include/tea_api.h @@ -30,6 +30,4 @@ int tea_switch_server(int newServerID); int tea_fetch_server(); -void tea_read_urls(struct tea_server_urls *wrData); - #endif diff --git a/client-frontend/dragon-tea/include/tea_structs.h b/client-frontend/dragon-tea/include/tea_structs.h index 9b6ad3f..5799228 100644 --- a/client-frontend/dragon-tea/include/tea_structs.h +++ b/client-frontend/dragon-tea/include/tea_structs.h @@ -122,6 +122,10 @@ struct tea_settings int active_server; // loaded from configurations char servers[32][255]; + // show log window + int show_logs; + // remove old notification + int old_notify_remove; // User messages GArray *local_msg_db; // Log I/O @@ -162,11 +166,14 @@ struct tea_app_widgets GtkWidget *top_label_user_state; guint timeout_periodic_sync; gboolean chat_synched; + gboolean firstTime; } chat_tab; struct { GtkWidget *combx_server_list; + GtkWidget *toggle_log; + GtkWidget *toggle_notify; GtkWidget *button_apply; } settings_tab; @@ -175,6 +182,8 @@ struct tea_app_widgets GtkWidget *widget_settings; GtkWindow *main_window; + GtkWindow *log_window; + GtkWidget *notebook; }; diff --git a/client-frontend/dragon-tea/include/ui_callbacks.h b/client-frontend/dragon-tea/include/ui_callbacks.h index c839933..627d17b 100644 --- a/client-frontend/dragon-tea/include/ui_callbacks.h +++ b/client-frontend/dragon-tea/include/ui_callbacks.h @@ -5,8 +5,6 @@ void tea_on_authenticate(const struct tea_id_info *user_info); -void tea_on_logouted(); - void ui_on_close_window(GtkWidget *window, gpointer data); void ui_on_notebook_switch_page(GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer user_data); diff --git a/client-frontend/dragon-tea/src/core/ui.c b/client-frontend/dragon-tea/src/core/ui.c index 0fc76c1..227af59 100644 --- a/client-frontend/dragon-tea/src/core/ui.c +++ b/client-frontend/dragon-tea/src/core/ui.c @@ -76,24 +76,11 @@ void tea_ui_init() tea_try_login(); tea_ui_focus_tab(UI_TAB_AUTH); - show_log_dialog(); -} + // libnotify init + notify_init("Dragon Tea Messenger"); -void tea_ui_update_settings() -{ - int selServer = 0; - for(int x = 0; x < 32; ++x) - { - if(strlen(app_settings.servers[x]) == 0) - break; - - if(tea_get_server_id(app_settings.servers[x]) == app_settings.active_server) - { - selServer = x; - break; - } - } - gtk_combo_box_set_active(GTK_COMBO_BOX(widgets.settings_tab.combx_server_list), selServer); + if(env.show_logs) + show_log_dialog(); } void tea_ui_focus_tab(enum UiTabs tabIndex) @@ -126,7 +113,9 @@ void tea_ui_chat_interactable(int value) void tea_ui_chat_sync() { widgets.chat_tab.chat_synched = FALSE; - on_chat_message_handler_async(NULL); + + if(tea_is_connected()) + on_chat_message_handler_async(NULL); } void tea_ui_chat_status_text(const char *status_text) @@ -167,7 +156,7 @@ void tea_ui_chat_push_block(const struct tea_message_id *message) { /* * FORMAT VIEW for Message Block - * bad@(21:16): Hello + * bad@[21:16]: Hello */ if(message == NULL) @@ -176,12 +165,40 @@ void tea_ui_chat_push_block(const struct tea_message_id *message) return; } - static const char format_message_block[] = "\n\n%s@(%s): %s\n"; - GDateTime *_gdatetime = g_date_time_new_from_unix_local(message->time_received); - gchar *date_time = g_date_time_format(_gdatetime, "%H:%M"); + static const char format_message_block[] = "\n\n>>%s@[%s]: %s\n"; - int require_size = snprintf(NULL, 0, format_message_block, message->sent_user_name, date_time, message->message_text); + gchar *date_time; + GDateTime *prevgtime, *_gdatetime = g_date_time_new_from_unix_utc(message->time_received); + if(env.local_msg_db->len == 0) + { + prevgtime = _gdatetime; + } + else + { + prevgtime = g_date_time_new_from_unix_utc( + g_array_index(env.local_msg_db, struct tea_message_id, (env.local_msg_db->len - 1)).time_received); + } + + // TODO: sort by date + + if(prevgtime == _gdatetime || + !(g_date_time_get_day_of_month(prevgtime) == g_date_time_get_day_of_month(_gdatetime) && + g_date_time_get_month(prevgtime) == g_date_time_get_month(_gdatetime) && + g_date_time_get_year(prevgtime) == g_date_time_get_year(_gdatetime))) + { + date_time = g_date_time_format(prevgtime, "\n\n\t::::%d.%m.%Y::::\n"); + + tea_ui_chat_push_text_raw(date_time, -1); + + g_free(date_time); + } + + if(prevgtime != _gdatetime) + g_free(prevgtime); + + date_time = g_date_time_format(_gdatetime, "%H:%M"); + int require_size = snprintf(NULL, 0, format_message_block, message->sent_user_name, date_time, message->message_text); char *text_buffer = (char *) malloc(require_size + 1); if(text_buffer == NULL) ui_error_fail("Out of memory!"); diff --git a/client-frontend/dragon-tea/src/core/ui_callbacks.c b/client-frontend/dragon-tea/src/core/ui_callbacks.c index b0bda07..9f7e48f 100644 --- a/client-frontend/dragon-tea/src/core/ui_callbacks.c +++ b/client-frontend/dragon-tea/src/core/ui_callbacks.c @@ -21,7 +21,7 @@ gpointer async_send(const char *text) int len = strlen(text); // send message to - net_api_write_message(&app_settings.id_info, -1, text, len, &last_send_result); + net_api_write_message(&env.id_info, -1, text, len, &last_send_result); // set work complete thread_send_msg = NULL; @@ -33,17 +33,17 @@ gpointer async_reply(gpointer) // Последнее сообщение на локальной машине (когда на сервере она устарело) int last_local_msg_id; - if(app_settings.local_msg_db->len == 0) + if(env.local_msg_db->len == 0) { last_local_msg_id = 0; } else { - last_local_msg_id = (&g_array_index(app_settings.local_msg_db, struct tea_message_id, app_settings.local_msg_db->len - 1))->msg_id; + last_local_msg_id = (&g_array_index(env.local_msg_db, struct tea_message_id, env.local_msg_db->len - 1))->msg_id; } // Читаем сообщение других пользователей и поддерживаем коммуникацию - net_api_read_messages(&app_settings.id_info, -1, last_local_msg_id, MESSAGES_PER_REQUEST, &last_read_result); + net_api_read_messages(&env.id_info, -1, last_local_msg_id, MESSAGES_PER_REQUEST, &last_read_result); thread_reply_msg = NULL; @@ -106,6 +106,12 @@ gboolean on_chat_sending_async(const gchar *text) return worked == FALSE; } +void notify_action(NotifyNotification *notification, const char *action, gpointer user_data) +{ + ui_error(action); + gtk_window_set_focus(widgets.main_window, NULL); +} + gboolean on_chat_message_handler_async(gpointer) { char buffer[128]; @@ -138,10 +144,14 @@ gboolean on_chat_message_handler_async(gpointer) if(last_chance_state != CHANCE_TO_LOGOUT) strcpy(buffer, _("Your network has been restored. ")); else - buffer[0] = 0; + buffer[0] = NULL; strcat(buffer, _("You're online.")); tea_ui_chat_status_text(buffer); + + if(widgets.chat_tab.firstTime) + widgets.chat_tab.firstTime = FALSE; + break; } @@ -152,15 +162,31 @@ gboolean on_chat_message_handler_async(gpointer) break; } - // Добавление сообщений из загруженных в локальные - g_array_append_vals(app_settings.local_msg_db, last_read_result.messages->data, last_read_result.messages->len); - + NotifyNotification *gnotify; + struct tea_message_id *message; // Отображение собщений for(int x = 0; x < last_read_result.messages->len; ++x) { - tea_ui_chat_push_block(&g_array_index(last_read_result.messages, struct tea_message_id, x)); + message = &g_array_index(last_read_result.messages, struct tea_message_id, x); + tea_ui_chat_push_block(message); + if(!widgets.chat_tab.firstTime && message->sent_user_id != env.id_info.user_id && + !gtk_window_is_active(widgets.main_window)) + { + gnotify = notify_notification_new( + message->sent_user_name, message->message_text, gtk_window_get_icon_name(widgets.main_window)); + notify_notification_add_action(gnotify, "custom_action", _("Read message"), notify_action, NULL, NULL); + + if(!env.old_notify_remove) + notify_notification_set_timeout(gnotify, 0); + + notify_notification_show(gnotify, NULL); + g_object_unref(gnotify); + } + g_array_append_val(env.local_msg_db, *message); } + // Have notify + // Освобождение старого массива g_array_free(last_read_result.messages, TRUE); last_read_result.messages = NULL; @@ -211,7 +237,7 @@ gboolean on_chat_message_handler_async(gpointer) thread_reply_msg = g_thread_new(NULL, (GThreadFunc) async_reply, NULL); } } - return TRUE; // EVERYTHING + return tea_is_connected(); // EVERYTHING } void ui_on_close_window(GtkWidget *window, gpointer data) @@ -257,7 +283,7 @@ void on_chat_send_button(GtkWidget *widget, gpointer data) void tea_on_authenticate(const struct tea_id_info *user_info) { char buffer[300], buf2[32]; - app_settings.connected = TRUE; + env.connected = TRUE; tea_ui_chat_clear(); @@ -304,6 +330,7 @@ void tea_on_authenticate(const struct tea_id_info *user_info) // reset chances check_chance_logouting = CHANCE_TO_LOGOUT; + widgets.chat_tab.firstTime = TRUE; // sync tea_ui_chat_sync(); @@ -311,12 +338,12 @@ void tea_on_authenticate(const struct tea_id_info *user_info) widgets.chat_tab.timeout_periodic_sync = g_timeout_add(INTERVAL_CHAT_SYNC, (GSourceFunc) on_chat_message_handler_async, NULL); } -void tea_on_logouted() +void tea_logout() { - if(!app_settings.connected) + if(!env.connected) return; - app_settings.connected = FALSE; + env.connected = FALSE; // remove message handler if(widgets.chat_tab.timeout_periodic_sync) @@ -335,7 +362,7 @@ void tea_on_logouted() GThread *sender = thread_reply_msg; if(sender) g_thread_join(sender); - // saved old data, reset at + // saved old data, reset it if(last_read_result.messages) { for(int x = 0; x < last_read_result.messages->len; ++x) @@ -343,16 +370,16 @@ void tea_on_logouted() free(g_array_index(last_read_result.messages, struct tea_message_id, x).message_text); } g_array_free(last_read_result.messages, TRUE); - memset(&last_read_result, 0, sizeof(last_read_result)); } + memset(&last_read_result, 0, sizeof(last_read_result)); // Clear local messages - for(size_t x = 0; x < app_settings.local_msg_db->len; ++x) + for(size_t x = 0; x < env.local_msg_db->len; ++x) { - free(g_array_index(app_settings.local_msg_db, struct tea_message_id, x).message_text); + free(g_array_index(env.local_msg_db, struct tea_message_id, x).message_text); } - g_array_free(app_settings.local_msg_db, TRUE); - app_settings.local_msg_db = g_array_new(FALSE, FALSE, sizeof(struct tea_message_id)); + g_array_free(env.local_msg_db, TRUE); + env.local_msg_db = g_array_new(FALSE, FALSE, sizeof(struct tea_message_id)); #ifdef TEA_OS_LINUX // Release RESIDENT SET SIZE (RSS) and put to System diff --git a/client-frontend/dragon-tea/src/core/ui_logs.c b/client-frontend/dragon-tea/src/core/ui_logs.c index 849d5fc..65c1796 100644 --- a/client-frontend/dragon-tea/src/core/ui_logs.c +++ b/client-frontend/dragon-tea/src/core/ui_logs.c @@ -9,17 +9,19 @@ void tea_log(const char *message) return; } + printf("%s\n", message); + GtkTextIter eIter; - gtk_text_buffer_get_end_iter(app_settings.log_buffer, &eIter); - gtk_text_buffer_insert(app_settings.log_buffer, &eIter, message, -1); + gtk_text_buffer_get_end_iter(env.log_buffer, &eIter); + gtk_text_buffer_insert(env.log_buffer, &eIter, message, -1); - gtk_text_buffer_get_end_iter(app_settings.log_buffer, &eIter); - gtk_text_buffer_insert(app_settings.log_buffer, &eIter, "\n", -1); + gtk_text_buffer_get_end_iter(env.log_buffer, &eIter); + gtk_text_buffer_insert(env.log_buffer, &eIter, "\n", -1); } void tea_clear_log() { - gtk_text_buffer_set_text(app_settings.log_buffer, "", 0); + gtk_text_buffer_set_text(env.log_buffer, "", 0); } void tea_ui_clear_buffer(GtkWidget *, gpointer) @@ -33,9 +35,10 @@ void show_log_dialog() gtk_window_get_position(widgets.main_window, &x, &y); gtk_window_get_size(widgets.main_window, &w, NULL); - GtkWindow *log_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_default_size(log_window, 300, 400); - gtk_window_move(log_window, x + w, y); + widgets.log_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + + gtk_window_set_default_size(widgets.log_window, 300, 400); + gtk_window_move(widgets.log_window, x + w, y); GtkBox *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); GtkWidget *scrolled_text = gtk_scrolled_window_new(NULL, NULL); @@ -43,7 +46,7 @@ void show_log_dialog() gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_text), GTK_SHADOW_IN); gtk_scrolled_window_set_kinetic_scrolling(GTK_SCROLLED_WINDOW(scrolled_text), TRUE); - GtkWidget *textView = gtk_text_view_new_with_buffer(app_settings.log_buffer); + GtkWidget *textView = gtk_text_view_new_with_buffer(env.log_buffer); gtk_text_view_set_editable(GTK_TEXT_VIEW(textView), FALSE); gtk_container_add(GTK_CONTAINER(scrolled_text), textView); @@ -55,6 +58,6 @@ void show_log_dialog() gtk_box_pack_end(box, clearButton, FALSE, TRUE, 0); - gtk_container_add(GTK_CONTAINER(log_window), box); - gtk_widget_show_all(GTK_WIDGET(log_window)); + gtk_container_add(GTK_CONTAINER(widgets.log_window), box); + gtk_widget_show_all(GTK_WIDGET(widgets.log_window)); } diff --git a/client-frontend/dragon-tea/src/core/ui_settings.c b/client-frontend/dragon-tea/src/core/ui_settings.c index 8b5f7d3..6f0e68b 100644 --- a/client-frontend/dragon-tea/src/core/ui_settings.c +++ b/client-frontend/dragon-tea/src/core/ui_settings.c @@ -1,16 +1,57 @@ #include "tea.h" +struct +{ + int toggle_log; + int toggle_notify; + int toggle_server; +} ref_setting; + void apply_changes() { - tea_logout(); + env.show_logs = ref_setting.toggle_log; + env.old_notify_remove = ref_setting.toggle_notify; + ref_setting.toggle_server = + tea_get_server_id(env.servers[gtk_combo_box_get_active(GTK_COMBO_BOX(widgets.settings_tab.combx_server_list))]); - int selected = gtk_combo_box_get_active(GTK_COMBO_BOX(widgets.settings_tab.combx_server_list)); + if(env.active_server != ref_setting.toggle_server) + { + tea_logout(); + tea_switch_server(ref_setting.toggle_server); + tea_try_login(); + } + tea_ui_focus_tab(UI_TAB_AUTH); +} - // Switch server - tea_switch_server(tea_get_server_id(app_settings.servers[selected])); +void toggle_button(GtkWidget *widget, gpointer data) +{ + (*(int *) data) = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); +} - tea_ui_focus_tab(UI_TAB_AUTH); - tea_try_login(); +void on_button_clk_show_log(GtkWidget *widget, gpointer data) +{ + show_log_dialog(); +} + +void tea_ui_update_settings() +{ + int selServer = 0; + for(int x = 0; x < 32; ++x) + { + if(strlen(env.servers[x]) == 0) + break; + + if(tea_get_server_id(env.servers[x]) == env.active_server) + { + selServer = x; + break; + } + } + gtk_combo_box_set_active(GTK_COMBO_BOX(widgets.settings_tab.combx_server_list), (ref_setting.toggle_server = selServer)); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widgets.settings_tab.toggle_log), (ref_setting.toggle_log = env.show_logs)); + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(widgets.settings_tab.toggle_notify), (ref_setting.toggle_notify = env.old_notify_remove)); } GtkWidget *create_settings_widget() @@ -23,13 +64,13 @@ GtkWidget *create_settings_widget() GtkListStore *server_list = gtk_list_store_new(1, G_TYPE_STRING); GtkTreeIter iter; - for(int x = 0; x < sizeof(app_settings.servers[0]); ++x) + for(int x = 0; x < sizeof(env.servers[0]); ++x) { - if(strlen(app_settings.servers[x]) == 0) + if(strlen(env.servers[x]) == 0) break; gtk_list_store_append(server_list, &iter); - gtk_list_store_set(server_list, &iter, 0, app_settings.servers[x], -1); + gtk_list_store_set(server_list, &iter, 0, env.servers[x], -1); } gtk_box_pack_start(GTK_BOX(widgetbox), gtk_label_new(_("Switch server: ")), TRUE, FALSE, 0); @@ -39,16 +80,27 @@ GtkWidget *create_settings_widget() gtk_widget_set_size_request(combobox, 200, 30); - // Создание отображения текста + // Show contents GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combobox), renderer, TRUE); gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combobox), renderer, "text", 0, NULL); - gtk_box_pack_start(GTK_BOX(widgetbox), combobox, TRUE, FALSE, 0); + GtkWidget *currentWidget = widgets.settings_tab.toggle_log = gtk_check_button_new_with_label(_("Show log window on startup")); + g_signal_connect(G_OBJECT(currentWidget), "toggled", G_CALLBACK(toggle_button), &ref_setting.toggle_log); + gtk_box_pack_start(GTK_BOX(widgetbox), currentWidget, TRUE, FALSE, 0); + + currentWidget = widgets.settings_tab.toggle_notify = gtk_check_button_new_with_label("Remove old notifications"); + + g_signal_connect(G_OBJECT(currentWidget), "clicked", G_CALLBACK(toggle_button), &ref_setting.toggle_notify); + gtk_box_pack_start(GTK_BOX(widgetbox), currentWidget, TRUE, FALSE, 0); + + currentWidget = gtk_button_new_with_label("Show log"); + g_signal_connect(G_OBJECT(currentWidget), "clicked", G_CALLBACK(on_button_clk_show_log), NULL); + gtk_box_pack_start(GTK_BOX(widgetbox), currentWidget, TRUE, FALSE, 0); + GtkWidget *button_apply = widgets.settings_tab.button_apply = gtk_button_new_with_label(_("Apply changes")); g_signal_connect(button_apply, "clicked", G_CALLBACK(apply_changes), NULL); - gtk_box_pack_end(GTK_BOX(widgetbox), button_apply, TRUE, FALSE, 0); tea_ui_update_settings(); diff --git a/client-frontend/dragon-tea/src/main.c b/client-frontend/dragon-tea/src/main.c index a23a556..dd58ae6 100644 --- a/client-frontend/dragon-tea/src/main.c +++ b/client-frontend/dragon-tea/src/main.c @@ -1,5 +1,14 @@ +#include + #include "tea.h" +#define USE_ONCE_LAUNCH 0 + +#if USE_ONCE_LAUNCH +#include +#define TSEM_KNAME "dragon_tea_lock" +#endif + int main(int argc, char *argv[]) { setlocale(LC_ALL, ""); @@ -19,14 +28,52 @@ int main(int argc, char *argv[]) // GUI Init gtk_init(&argc, &argv); +#if USE_ONCE_LAUNCH + // Check is only one copy runs + sem_t *sem; + + sem = sem_open(TSEM_KNAME, O_CREAT | O_EXCL, 0644, 1); + if(sem == SEM_FAILED) + { + ui_error("Program already launched."); + return EXIT_FAILURE; + } + + if(sem_wait(sem) == -1) + { + perror("sem_wait"); + return EXIT_FAILURE; + } +#endif + // Run Dragon Tea Messenger tea_init(); // Window Looping gtk_main(); - // Free networks - net_free(); + // Free Unused resources DTM + tea_free(); + +#if USE_ONCE_LAUNCH + // Close launch + if(sem_post(sem) == -1) + { + perror("sem_post"); + return EXIT_FAILURE; + } + if(sem_close(sem) == -1) + { + perror("sem_close"); + return EXIT_FAILURE; + } + + if(sem_unlink(TSEM_KNAME) == -1) + { + perror("sem_unlink"); + return EXIT_FAILURE; + } +#endif - return 0; + return EXIT_SUCCESS; } diff --git a/client-frontend/dragon-tea/src/net/tea_net_api.c b/client-frontend/dragon-tea/src/net/tea_net_api.c index 5901f78..3ec5640 100644 --- a/client-frontend/dragon-tea/src/net/tea_net_api.c +++ b/client-frontend/dragon-tea/src/net/tea_net_api.c @@ -465,11 +465,11 @@ int net_api_signup(const char *nickname, tea_register_result *output) const char *tea_url_server() { int s = -1; - for(int x = 0; x < sizeof(app_settings.servers) / sizeof(app_settings.servers[0]); ++x) + for(int x = 0; x < sizeof(env.servers) / sizeof(env.servers[0]); ++x) { - if(strlen(app_settings.servers[x]) == 0) + if(strlen(env.servers[x]) == 0) break; - if(app_settings.active_server == tea_get_server_id(app_settings.servers[x])) + if(env.active_server == tea_get_server_id(env.servers[x])) { s = x; break; @@ -481,12 +481,12 @@ const char *tea_url_server() return NULL; } - return app_settings.servers[s]; + return env.servers[s]; } int tea_switch_server(int newServerID) { - app_settings.active_server = newServerID; + env.active_server = newServerID; // init new server ID tea_read_urls(&cur_server.urls); @@ -571,7 +571,7 @@ void tea_read_urls(struct tea_server_urls *wrData) if(server == NULL) { - printf("server == NULL"); + tea_log("server == NULL"); return; } diff --git a/client-frontend/dragon-tea/src/tea.c b/client-frontend/dragon-tea/src/tea.c index 10e72d4..4f86614 100644 --- a/client-frontend/dragon-tea/src/tea.c +++ b/client-frontend/dragon-tea/src/tea.c @@ -9,7 +9,7 @@ #include "ui_callbacks.h" -struct tea_settings app_settings; +struct tea_settings env; const char *get_conf_dir(); @@ -25,6 +25,12 @@ void tea_init() tea_ui_init(); } +void tea_free() +{ + net_free(); + notify_uninit(); +} + void tea_load_conf(struct tea_settings *tea, const char *filename); void tea_save_conf(const struct tea_settings *save_tea, const char *filename); @@ -70,15 +76,14 @@ const char *tea_version() int tea_is_connected() { - return app_settings.connected; + return env.connected; } void tea_login(const struct tea_id_info *login_info) { - if(tea_is_connected()) - tea_logout(); + tea_logout(); - memcpy(&(app_settings.id_info), login_info, sizeof(app_settings.id_info)); + memcpy(&(env.id_info), login_info, sizeof(env.id_info)); // event on authenticate tea_on_authenticate(login_info); @@ -86,24 +91,19 @@ void tea_login(const struct tea_id_info *login_info) int tea_try_login() { - int result = app_settings.id_info.user_id != -1 && strlen(app_settings.id_info.user_nickname) > 0; + int result = env.id_info.user_id != -1 && strlen(env.id_info.user_nickname) > 0; if(result) { - tea_ui_auth_set_id(app_settings.id_info.user_id); + tea_ui_auth_set_id(env.id_info.user_id); tea_ui_auth_sigin(); } return result; } -void tea_logout() -{ - tea_on_logouted(); -} - const char *get_conf_dir() { const char *home_dir; - if(strlen(app_settings.config_dir) == 0) + if(strlen(env.config_dir) == 0) { #ifdef TEA_OS_LINUX @@ -113,9 +113,9 @@ const char *get_conf_dir() home_dir = "/tmp/temp-user-tea"; // set as default to tmp mkdir(home_dir, 0700); } - strncpy(app_settings.config_dir, home_dir, sizeof(app_settings.config_dir)); - strncat(app_settings.config_dir, "/.config/DragonTea", sizeof(app_settings.config_dir)); - if(mkdir(app_settings.config_dir, 0700) != 0 && errno != EEXIST) + strncpy(env.config_dir, home_dir, sizeof(env.config_dir)); + strncat(env.config_dir, "/.config/DragonTea", sizeof(env.config_dir)); + if(mkdir(env.config_dir, 0700) != 0 && errno != EEXIST) { printf("%s", strerror(errno)); } @@ -128,27 +128,27 @@ const char *get_conf_dir() #endif } - return app_settings.config_dir; + return env.config_dir; } void tea_load() { const char *conf_dir = get_conf_dir(); - strncat(app_settings.setting_filename, conf_dir, sizeof(app_settings.setting_filename) - 1); - strncat(app_settings.setting_filename, "/tea-config.json", sizeof(app_settings.setting_filename) - 1); - app_settings.local_msg_db = g_array_new(FALSE, FALSE, sizeof(struct tea_message_id)); - tea_load_conf(&app_settings, app_settings.setting_filename); + strncat(env.setting_filename, conf_dir, sizeof(env.setting_filename) - 1); + strncat(env.setting_filename, "/tea-config.json", sizeof(env.setting_filename) - 1); + env.local_msg_db = g_array_new(FALSE, FALSE, sizeof(struct tea_message_id)); + tea_load_conf(&env, env.setting_filename); // Init logs - app_settings.log_buffer = gtk_text_buffer_new(NULL); + env.log_buffer = gtk_text_buffer_new(NULL); // switching server - tea_switch_server(app_settings.active_server); + tea_switch_server(env.active_server); } void tea_save() { - tea_save_conf(&app_settings, app_settings.setting_filename); + tea_save_conf(&env, env.setting_filename); } void tea_load_conf(struct tea_settings *tea, const char *filename) @@ -157,7 +157,7 @@ void tea_load_conf(struct tea_settings *tea, const char *filename) int deltaFlag, validate; size_t len; FILE *config_file; - struct json_object *userId, *user_nickname, *active_server, *servers, *server, *parser; + struct json_object *userId, *user_nickname, *active_server, *servers, *show_logs, *old_notify, *server, *parser; // File not permit // then set application settings to default @@ -209,6 +209,14 @@ void tea_load_conf(struct tea_settings *tea, const char *filename) validate |= 4; if(!json_object_object_get_ex(parser, "servers", &servers) || !json_object_is_type(servers, json_type_array)) validate |= 8; + if(!json_object_object_get_ex(parser, "show_logs", &show_logs) || !json_object_is_type(show_logs, json_type_boolean)) + tea->show_logs = 1; // Show as default + else + tea->show_logs = (int) json_object_get_boolean(show_logs); + if(!json_object_object_get_ex(parser, "remove_old_notify", &old_notify) || !json_object_is_type(old_notify, json_type_boolean)) + tea->old_notify_remove = 1; // Remove old notify = yes as default + else + tea->old_notify_remove = (int) json_object_get_boolean(old_notify); // nickname and userId if((validate & 3) == 0) @@ -273,11 +281,12 @@ void tea_save_conf(const struct tea_settings *save_tea, const char *filename) for(len = 0, cmp1 = 1; strlen(_from.servers[len]); ++len) cmp1 *= 1 | tea_get_server_id(_from.servers[len]); - for(len = 0, cmp2 = 1; strlen(app_settings.servers[len]); ++len) - cmp2 *= 1 | tea_get_server_id(app_settings.servers[len]); + for(len = 0, cmp2 = 1; strlen(env.servers[len]); ++len) + cmp2 *= 1 | tea_get_server_id(env.servers[len]); if(_from.id_info.user_id == save_tea->id_info.user_id && strcmp(save_tea->id_info.user_nickname, _from.id_info.user_nickname) == 0 && - _from.active_server == app_settings.active_server && cmp1 == cmp2) + _from.active_server == env.active_server && cmp1 == cmp2 && save_tea->show_logs == _from.show_logs && + save_tea->old_notify_remove == _from.old_notify_remove) { return; } @@ -286,13 +295,15 @@ void tea_save_conf(const struct tea_settings *save_tea, const char *filename) json_object_object_add(jdata, "user_id", json_object_new_int64(save_tea->id_info.user_id)); json_object_object_add(jdata, "user_nickname", json_object_new_string(save_tea->id_info.user_nickname)); json_object_object_add(jdata, "active_server", json_object_new_int(save_tea->active_server)); + json_object_object_add(jdata, "show_logs", json_object_new_boolean(save_tea->show_logs)); + json_object_object_add(jdata, "remove_old_notify", json_object_new_boolean(save_tea->old_notify_remove)); // save server list jarr = json_object_new_array_ext(len); for(; len-- > 0;) { - json_object_array_add(jarr, json_object_new_string(app_settings.servers[len])); + json_object_array_add(jarr, json_object_new_string(env.servers[len])); } json_object_object_add(jdata, "servers", jarr); diff --git a/client-frontend/webclient/index.html b/client-frontend/webclient/index.html index e2b8d2b..73fd7e8 100644 --- a/client-frontend/webclient/index.html +++ b/client-frontend/webclient/index.html @@ -19,7 +19,7 @@

Не выполнен вход.

- +

(!) для входа требуется только UserID которое выдано лично вам.

Данная Веб странница под лицензией

+
+ +
+