aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheJackiMonster <thejackimonster@gmail.com>2022-03-14 14:33:21 +0100
committerTheJackiMonster <thejackimonster@gmail.com>2022-03-14 14:33:21 +0100
commit8ac4536fbfe1bbcc6da753e3bea2944d0c937323 (patch)
tree7aadc964221dfbae2c84105c5764dce2f09be993
parent43019c37a2a12147c401d75327e19e2ac383d6f4 (diff)
downloadmessenger-gtk-8ac4536fbfe1bbcc6da753e3bea2944d0c937323.tar.gz
messenger-gtk-8ac4536fbfe1bbcc6da753e3bea2944d0c937323.zip
Added interface to record audio messages
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
-rw-r--r--resources/ui/chat.ui212
-rw-r--r--src/ui/chat.c210
-rw-r--r--src/ui/chat.h12
3 files changed, 370 insertions, 64 deletions
diff --git a/resources/ui/chat.ui b/resources/ui/chat.ui
index 5f50cbd..0c08970 100644
--- a/resources/ui/chat.ui
+++ b/resources/ui/chat.ui
@@ -311,69 +311,181 @@ Author: Tobias Frisch
311 <property name="border-width">4</property> 311 <property name="border-width">4</property>
312 <property name="spacing">4</property> 312 <property name="spacing">4</property>
313 <child> 313 <child>
314 <object class="GtkButton" id="attach_file_button"> 314 <object class="GtkStack" id="send_stack">
315 <property name="visible">True</property> 315 <property name="visible">True</property>
316 <property name="sensitive">False</property> 316 <property name="can-focus">False</property>
317 <property name="can-focus">True</property> 317 <property name="transition-type">slide-up</property>
318 <property name="receives-default">True</property>
319 <property name="valign">center</property>
320 <property name="relief">none</property>
321 <child> 318 <child>
322 <object class="GtkImage"> 319 <object class="GtkBox" id="send_text_box">
323 <property name="visible">True</property> 320 <property name="visible">True</property>
324 <property name="can-focus">False</property> 321 <property name="can-focus">False</property>
325 <property name="icon-name">mail-attachment-symbolic</property> 322 <property name="spacing">4</property>
323 <child>
324 <object class="GtkButton" id="attach_file_button">
325 <property name="visible">True</property>
326 <property name="sensitive">False</property>
327 <property name="can-focus">True</property>
328 <property name="receives-default">True</property>
329 <property name="valign">center</property>
330 <property name="relief">none</property>
331 <child>
332 <object class="GtkImage">
333 <property name="visible">True</property>
334 <property name="can-focus">False</property>
335 <property name="icon-name">mail-attachment-symbolic</property>
336 </object>
337 </child>
338 </object>
339 <packing>
340 <property name="expand">False</property>
341 <property name="fill">True</property>
342 <property name="position">0</property>
343 </packing>
344 </child>
345 <child>
346 <object class="GtkTextView" id="send_text_view">
347 <property name="width-request">210</property>
348 <property name="height-request">48</property>
349 <property name="visible">True</property>
350 <property name="sensitive">False</property>
351 <property name="can-focus">True</property>
352 <property name="valign">end</property>
353 <property name="editable">False</property>
354 <property name="wrap-mode">word-char</property>
355 <property name="left-margin">8</property>
356 <property name="right-margin">8</property>
357 <property name="top-margin">8</property>
358 <property name="bottom-margin">8</property>
359 <property name="input-hints">GTK_INPUT_HINT_SPELLCHECK | GTK_INPUT_HINT_WORD_COMPLETION | GTK_INPUT_HINT_INHIBIT_OSK | GTK_INPUT_HINT_EMOJI | GTK_INPUT_HINT_NONE</property>
360 </object>
361 <packing>
362 <property name="expand">True</property>
363 <property name="fill">True</property>
364 <property name="position">1</property>
365 </packing>
366 </child>
367 <child>
368 <object class="GtkButton" id="emoji_button">
369 <property name="visible">True</property>
370 <property name="sensitive">False</property>
371 <property name="can-focus">True</property>
372 <property name="receives-default">True</property>
373 <property name="valign">center</property>
374 <property name="relief">none</property>
375 <child>
376 <object class="GtkImage">
377 <property name="visible">True</property>
378 <property name="can-focus">False</property>
379 <property name="icon-name">face-smile-symbolic</property>
380 </object>
381 </child>
382 </object>
383 <packing>
384 <property name="expand">False</property>
385 <property name="fill">True</property>
386 <property name="position">2</property>
387 </packing>
388 </child>
326 </object> 389 </object>
390 <packing>
391 <property name="name">page_send_text</property>
392 </packing>
327 </child> 393 </child>
328 </object>
329 <packing>
330 <property name="expand">False</property>
331 <property name="fill">True</property>
332 <property name="position">0</property>
333 </packing>
334 </child>
335 <child>
336 <object class="GtkTextView" id="send_text_view">
337 <property name="width-request">210</property>
338 <property name="height-request">48</property>
339 <property name="visible">True</property>
340 <property name="sensitive">False</property>
341 <property name="can-focus">True</property>
342 <property name="valign">end</property>
343 <property name="editable">False</property>
344 <property name="wrap-mode">word-char</property>
345 <property name="left-margin">8</property>
346 <property name="right-margin">8</property>
347 <property name="top-margin">8</property>
348 <property name="bottom-margin">8</property>
349 <property name="input-hints">GTK_INPUT_HINT_SPELLCHECK | GTK_INPUT_HINT_WORD_COMPLETION | GTK_INPUT_HINT_INHIBIT_OSK | GTK_INPUT_HINT_EMOJI | GTK_INPUT_HINT_NONE</property>
350 </object>
351 <packing>
352 <property name="expand">True</property>
353 <property name="fill">True</property>
354 <property name="position">1</property>
355 </packing>
356 </child>
357 <child>
358 <object class="GtkButton" id="emoji_button">
359 <property name="visible">True</property>
360 <property name="sensitive">False</property>
361 <property name="can-focus">True</property>
362 <property name="receives-default">True</property>
363 <property name="valign">center</property>
364 <property name="relief">none</property>
365 <child> 394 <child>
366 <object class="GtkImage"> 395 <object class="GtkBox" id="send_recording_box">
367 <property name="visible">True</property> 396 <property name="visible">True</property>
368 <property name="can-focus">False</property> 397 <property name="can-focus">False</property>
369 <property name="icon-name">face-smile-symbolic</property> 398 <property name="spacing">4</property>
399 <child>
400 <object class="GtkButton" id="recording_close_button">
401 <property name="visible">True</property>
402 <property name="can-focus">True</property>
403 <property name="receives-default">True</property>
404 <property name="valign">center</property>
405 <property name="relief">none</property>
406 <child>
407 <object class="GtkImage">
408 <property name="visible">True</property>
409 <property name="can-focus">False</property>
410 <property name="icon-name">window-close-symbolic</property>
411 </object>
412 </child>
413 </object>
414 <packing>
415 <property name="expand">False</property>
416 <property name="fill">True</property>
417 <property name="position">0</property>
418 </packing>
419 </child>
420 <child>
421 <object class="GtkButton" id="recording_play_button">
422 <property name="visible">True</property>
423 <property name="can-focus">True</property>
424 <property name="receives-default">True</property>
425 <property name="valign">center</property>
426 <property name="relief">none</property>
427 <child>
428 <object class="GtkImage" id="play_pause_symbol">
429 <property name="visible">True</property>
430 <property name="can-focus">False</property>
431 <property name="icon-name">media-playback-start-symbolic</property>
432 </object>
433 </child>
434 </object>
435 <packing>
436 <property name="expand">False</property>
437 <property name="fill">True</property>
438 <property name="position">1</property>
439 </packing>
440 </child>
441 <child>
442 <object class="GtkBox">
443 <property name="visible">True</property>
444 <property name="can-focus">False</property>
445 <property name="valign">center</property>
446 <property name="orientation">vertical</property>
447 <property name="spacing">2</property>
448 <child>
449 <object class="GtkLabel" id="recording_label">
450 <property name="visible">True</property>
451 <property name="can-focus">False</property>
452 <property name="label" translatable="yes">00:00</property>
453 </object>
454 <packing>
455 <property name="expand">False</property>
456 <property name="fill">True</property>
457 <property name="position">0</property>
458 </packing>
459 </child>
460 <child>
461 <object class="GtkProgressBar" id="recording_progress_bar">
462 <property name="visible">True</property>
463 <property name="can-focus">False</property>
464 </object>
465 <packing>
466 <property name="expand">False</property>
467 <property name="fill">True</property>
468 <property name="position">1</property>
469 </packing>
470 </child>
471 </object>
472 <packing>
473 <property name="expand">True</property>
474 <property name="fill">True</property>
475 <property name="position">2</property>
476 </packing>
477 </child>
370 </object> 478 </object>
479 <packing>
480 <property name="name">page_send_recording</property>
481 <property name="position">1</property>
482 </packing>
371 </child> 483 </child>
372 </object> 484 </object>
373 <packing> 485 <packing>
374 <property name="expand">False</property> 486 <property name="expand">True</property>
375 <property name="fill">True</property> 487 <property name="fill">True</property>
376 <property name="position">2</property> 488 <property name="position">0</property>
377 </packing> 489 </packing>
378 </child> 490 </child>
379 <child> 491 <child>
@@ -395,7 +507,7 @@ Author: Tobias Frisch
395 <packing> 507 <packing>
396 <property name="expand">False</property> 508 <property name="expand">False</property>
397 <property name="fill">True</property> 509 <property name="fill">True</property>
398 <property name="position">3</property> 510 <property name="position">1</property>
399 </packing> 511 </packing>
400 </child> 512 </child>
401 </object> 513 </object>
diff --git a/src/ui/chat.c b/src/ui/chat.c
index 953bf7e..71ea810 100644
--- a/src/ui/chat.c
+++ b/src/ui/chat.c
@@ -328,11 +328,10 @@ close_dialog:
328} 328}
329 329
330static void 330static void
331handle_send_text_buffer_changed(GtkTextBuffer *buffer, 331_update_send_record_symbol(GtkTextBuffer *buffer,
332 gpointer user_data) 332 GtkImage *symbol,
333 gboolean picker_revealed)
333{ 334{
334 GtkImage *symbol = GTK_IMAGE(user_data);
335
336 GtkTextIter start, end; 335 GtkTextIter start, end;
337 gtk_text_buffer_get_start_iter(buffer, &start); 336 gtk_text_buffer_get_start_iter(buffer, &start);
338 gtk_text_buffer_get_end_iter(buffer, &end); 337 gtk_text_buffer_get_end_iter(buffer, &end);
@@ -341,13 +340,26 @@ handle_send_text_buffer_changed(GtkTextBuffer *buffer,
341 340
342 gtk_image_set_from_icon_name( 341 gtk_image_set_from_icon_name(
343 symbol, 342 symbol,
344 0 < strlen(text)? 343 (0 < strlen(text)) || (picker_revealed)?
345 "mail-send-symbolic" : 344 "mail-send-symbolic" :
346 "audio-input-microphone-symbolic", 345 "audio-input-microphone-symbolic",
347 GTK_ICON_SIZE_BUTTON 346 GTK_ICON_SIZE_BUTTON
348 ); 347 );
349} 348}
350 349
350static void
351handle_send_text_buffer_changed(GtkTextBuffer *buffer,
352 gpointer user_data)
353{
354 UI_CHAT_Handle *handle = (UI_CHAT_Handle*) user_data;
355
356 _update_send_record_symbol(
357 buffer,
358 handle->send_record_symbol,
359 gtk_revealer_get_child_revealed(handle->picker_revealer)
360 );
361}
362
351static gboolean 363static gboolean
352_send_text_from_view(MESSENGER_Application *app, 364_send_text_from_view(MESSENGER_Application *app,
353 GtkTextView *text_view) 365 GtkTextView *text_view)
@@ -375,19 +387,112 @@ _send_text_from_view(MESSENGER_Application *app,
375} 387}
376 388
377static void 389static void
390_drop_any_recording(UI_CHAT_Handle *handle)
391{
392 _update_send_record_symbol(
393 gtk_text_view_get_buffer(handle->send_text_view),
394 handle->send_record_symbol,
395 FALSE
396 );
397
398 gtk_stack_set_visible_child(handle->send_stack, handle->send_text_box);
399
400 handle->recorded = FALSE;
401}
402
403static void
378handle_send_record_button_click(GtkButton *button, 404handle_send_record_button_click(GtkButton *button,
379 gpointer user_data) 405 gpointer user_data)
380{ 406{
381 MESSENGER_Application *app = (MESSENGER_Application*) user_data; 407 MESSENGER_Application *app = (MESSENGER_Application*) user_data;
382 408
383 GtkTextView *text_view = GTK_TEXT_VIEW( 409 UI_CHAT_Handle *handle = (UI_CHAT_Handle*) (
384 g_object_get_qdata(G_OBJECT(button), app->quarks.widget) 410 g_object_get_qdata(G_OBJECT(button), app->quarks.ui)
385 ); 411 );
386 412
387 if (!_send_text_from_view(app, text_view)) 413 if ((handle->recorded) &&
414 (!gtk_revealer_get_child_revealed(handle->picker_revealer)) &&
415 (gtk_stack_get_visible_child(handle->send_stack) ==
416 handle->send_recording_box))
388 { 417 {
389 // TODO: record audio and attach as file? 418 // TODO: send audio as file!
419
420 _drop_any_recording(handle);
421 return;
390 } 422 }
423
424 GtkTextView *text_view = GTK_TEXT_VIEW(
425 g_object_get_qdata(G_OBJECT(button), app->quarks.widget)
426 );
427
428 _send_text_from_view(app, text_view);
429}
430
431static gboolean
432handle_send_record_button_pressed(GtkWidget *widget,
433 UNUSED GdkEvent *event,
434 gpointer user_data)
435{
436 MESSENGER_Application *app = (MESSENGER_Application*) user_data;
437
438 UI_CHAT_Handle *handle = (UI_CHAT_Handle*) (
439 g_object_get_qdata(G_OBJECT(widget), app->quarks.ui)
440 );
441
442 if ((handle->recorded) ||
443 (gtk_revealer_get_child_revealed(handle->picker_revealer)) ||
444 (handle->send_text_box != gtk_stack_get_visible_child(handle->send_stack)))
445 return FALSE;
446
447 gtk_image_set_from_icon_name(
448 handle->play_pause_symbol,
449 "media-playback-start-symbolic",
450 GTK_ICON_SIZE_BUTTON
451 );
452
453 gtk_image_set_from_icon_name(
454 handle->send_record_symbol,
455 "media-record-symbolic",
456 GTK_ICON_SIZE_BUTTON
457 );
458
459 gtk_widget_set_sensitive(GTK_WIDGET(handle->recording_play_button), FALSE);
460
461 gtk_stack_set_visible_child(handle->send_stack, handle->send_recording_box);
462
463 return TRUE;
464}
465
466static gboolean
467handle_send_record_button_released(GtkWidget *widget,
468 UNUSED GdkEvent *event,
469 gpointer user_data)
470{
471 MESSENGER_Application *app = (MESSENGER_Application*) user_data;
472
473 UI_CHAT_Handle *handle = (UI_CHAT_Handle*) (
474 g_object_get_qdata(G_OBJECT(widget), app->quarks.ui)
475 );
476
477 if ((handle->recorded) ||
478 (gtk_revealer_get_child_revealed(handle->picker_revealer)) ||
479 (handle->send_recording_box != gtk_stack_get_visible_child(
480 handle->send_stack)))
481 return FALSE;
482
483 gtk_widget_set_sensitive(GTK_WIDGET(handle->recording_play_button), TRUE);
484
485 gtk_revealer_set_reveal_child(handle->picker_revealer, FALSE);
486
487 handle->recorded = TRUE;
488
489 gtk_image_set_from_icon_name(
490 handle->send_record_symbol,
491 "mail-send-symbolic",
492 GTK_ICON_SIZE_BUTTON
493 );
494
495 return TRUE;
391} 496}
392 497
393static gboolean 498static gboolean
@@ -407,13 +512,29 @@ handle_send_text_key_press (GtkWidget *widget,
407} 512}
408 513
409static void 514static void
515handle_recording_close_button_click(UNUSED GtkButton *button,
516 gpointer user_data)
517{
518 UI_CHAT_Handle *handle = (UI_CHAT_Handle*) user_data;
519
520 _drop_any_recording(handle);
521}
522
523static void
410handle_picker_button_click(UNUSED GtkButton *button, 524handle_picker_button_click(UNUSED GtkButton *button,
411 gpointer user_data) 525 gpointer user_data)
412{ 526{
413 GtkRevealer *revealer = GTK_REVEALER(user_data); 527 UI_CHAT_Handle *handle = (UI_CHAT_Handle*) user_data;
414 gboolean reveal = !gtk_revealer_get_child_revealed(revealer); 528
529 gboolean reveal = !gtk_revealer_get_child_revealed(handle->picker_revealer);
415 530
416 gtk_revealer_set_reveal_child(revealer, reveal); 531 gtk_revealer_set_reveal_child(handle->picker_revealer, reveal);
532
533 _update_send_record_symbol(
534 gtk_text_view_get_buffer(handle->send_text_view),
535 handle->send_record_symbol,
536 reveal
537 );
417} 538}
418 539
419UI_CHAT_Handle* 540UI_CHAT_Handle*
@@ -424,6 +545,8 @@ ui_chat_new(MESSENGER_Application *app)
424 UI_CHAT_Handle *handle = g_malloc(sizeof(UI_CHAT_Handle)); 545 UI_CHAT_Handle *handle = g_malloc(sizeof(UI_CHAT_Handle));
425 UI_MESSENGER_Handle *messenger = &(app->ui.messenger); 546 UI_MESSENGER_Handle *messenger = &(app->ui.messenger);
426 547
548 handle->recorded = FALSE;
549
427 handle->app = app; 550 handle->app = app;
428 551
429 handle->messages = NULL; 552 handle->messages = NULL;
@@ -605,6 +728,18 @@ ui_chat_new(MESSENGER_Application *app)
605 handle 728 handle
606 ); 729 );
607 730
731 handle->send_stack = GTK_STACK(
732 gtk_builder_get_object(handle->builder, "send_stack")
733 );
734
735 handle->send_text_box = GTK_WIDGET(
736 gtk_builder_get_object(handle->builder, "send_text_box")
737 );
738
739 handle->send_recording_box = GTK_WIDGET(
740 gtk_builder_get_object(handle->builder, "send_recording_box")
741 );
742
608 handle->attach_file_button = GTK_BUTTON( 743 handle->attach_file_button = GTK_BUTTON(
609 gtk_builder_get_object(handle->builder, "attach_file_button") 744 gtk_builder_get_object(handle->builder, "attach_file_button")
610 ); 745 );
@@ -640,7 +775,7 @@ ui_chat_new(MESSENGER_Application *app)
640 send_text_buffer, 775 send_text_buffer,
641 "changed", 776 "changed",
642 G_CALLBACK(handle_send_text_buffer_changed), 777 G_CALLBACK(handle_send_text_buffer_changed),
643 handle->send_record_symbol 778 handle
644 ); 779 );
645 780
646 g_signal_connect( 781 g_signal_connect(
@@ -651,6 +786,20 @@ ui_chat_new(MESSENGER_Application *app)
651 ); 786 );
652 787
653 g_signal_connect( 788 g_signal_connect(
789 handle->send_record_button,
790 "button-press-event",
791 G_CALLBACK(handle_send_record_button_pressed),
792 app
793 );
794
795 g_signal_connect(
796 handle->send_record_button,
797 "button-release-event",
798 G_CALLBACK(handle_send_record_button_released),
799 app
800 );
801
802 g_signal_connect(
654 handle->send_text_view, 803 handle->send_text_view,
655 "key-press-event", 804 "key-press-event",
656 G_CALLBACK(handle_send_text_key_press), 805 G_CALLBACK(handle_send_text_key_press),
@@ -675,6 +824,39 @@ ui_chat_new(MESSENGER_Application *app)
675 handle->send_text_view 824 handle->send_text_view
676 ); 825 );
677 826
827 g_object_set_qdata(
828 G_OBJECT(handle->send_record_button),
829 app->quarks.ui,
830 handle
831 );
832
833 handle->recording_close_button = GTK_BUTTON(
834 gtk_builder_get_object(handle->builder, "recording_close_button")
835 );
836
837 g_signal_connect(
838 handle->recording_close_button,
839 "clicked",
840 G_CALLBACK(handle_recording_close_button_click),
841 handle
842 );
843
844 handle->recording_play_button = GTK_BUTTON(
845 gtk_builder_get_object(handle->builder, "recording_play_button")
846 );
847
848 handle->play_pause_symbol = GTK_IMAGE(
849 gtk_builder_get_object(handle->builder, "play_pause_symbol")
850 );
851
852 handle->recording_label = GTK_LABEL(
853 gtk_builder_get_object(handle->builder, "recording_label")
854 );
855
856 handle->recording_progress_bar = GTK_PROGRESS_BAR(
857 gtk_builder_get_object(handle->builder, "recording_progress_bar")
858 );
859
678 handle->picker_revealer = GTK_REVEALER( 860 handle->picker_revealer = GTK_REVEALER(
679 gtk_builder_get_object(handle->builder, "picker_revealer") 861 gtk_builder_get_object(handle->builder, "picker_revealer")
680 ); 862 );
@@ -690,7 +872,7 @@ ui_chat_new(MESSENGER_Application *app)
690 handle->emoji_button, 872 handle->emoji_button,
691 "clicked", 873 "clicked",
692 G_CALLBACK(handle_picker_button_click), 874 G_CALLBACK(handle_picker_button_click),
693 handle->picker_revealer 875 handle
694 ); 876 );
695 877
696 return handle; 878 return handle;
diff --git a/src/ui/chat.h b/src/ui/chat.h
index 119071d..0134a85 100644
--- a/src/ui/chat.h
+++ b/src/ui/chat.h
@@ -38,6 +38,8 @@ typedef struct UI_FILE_LOAD_ENTRY_Handle UI_FILE_LOAD_ENTRY_Handle;
38 38
39typedef struct UI_CHAT_Handle 39typedef struct UI_CHAT_Handle
40{ 40{
41 gboolean recorded;
42
41 MESSENGER_Application *app; 43 MESSENGER_Application *app;
42 44
43 GList *messages; 45 GList *messages;
@@ -79,12 +81,22 @@ typedef struct UI_CHAT_Handle
79 GtkListBox *chat_files_listbox; 81 GtkListBox *chat_files_listbox;
80 GtkListBox *messages_listbox; 82 GtkListBox *messages_listbox;
81 83
84 GtkStack *send_stack;
85 GtkWidget *send_text_box;
86 GtkWidget *send_recording_box;
87
82 GtkButton *attach_file_button; 88 GtkButton *attach_file_button;
83 GtkTextView *send_text_view; 89 GtkTextView *send_text_view;
84 GtkButton *emoji_button; 90 GtkButton *emoji_button;
85 GtkButton *send_record_button; 91 GtkButton *send_record_button;
86 GtkImage *send_record_symbol; 92 GtkImage *send_record_symbol;
87 93
94 GtkButton *recording_close_button;
95 GtkButton *recording_play_button;
96 GtkImage *play_pause_symbol;
97 GtkLabel *recording_label;
98 GtkProgressBar *recording_progress_bar;
99
88 GtkRevealer *picker_revealer; 100 GtkRevealer *picker_revealer;
89 101
90 UI_PICKER_Handle *picker; 102 UI_PICKER_Handle *picker;