Improve Gtk4 port
|
@ -13,16 +13,14 @@ find_packages(MAIN_PACKAGES REQUIRED
|
|||
)
|
||||
|
||||
set(RESOURCE_LIST
|
||||
icons/dino-account-plus-symbolic.svg
|
||||
icons/dino-conversation-list-placeholder-arrow.svg
|
||||
icons/dino-qr-code-symbolic.svg
|
||||
icons/dino-party-popper-symbolic.svg
|
||||
icons/dino-status-away.svg
|
||||
icons/dino-status-chat.svg
|
||||
icons/dino-status-dnd.svg
|
||||
icons/dino-status-online.svg
|
||||
icons/im.dino.Dino.svg
|
||||
|
||||
icons/scalable/actions/dino-account-plus-symbolic.svg
|
||||
|
||||
icons/scalable/apps/im.dino.Dino-symbolic.svg
|
||||
|
||||
icons/scalable/devices/dino-device-desktop-symbolic.svg
|
||||
|
@ -43,8 +41,6 @@ set(RESOURCE_LIST
|
|||
icons/scalable/mimetypes/dino-file-table-symbolic.svg
|
||||
icons/scalable/mimetypes/dino-file-video-symbolic.svg
|
||||
|
||||
icons/scalable/status/dino-changes-allowed-symbolic.svg
|
||||
icons/scalable/status/dino-changes-prevent-symbolic.svg
|
||||
icons/scalable/status/dino-double-tick-symbolic.svg
|
||||
icons/scalable/status/dino-microphone-off-symbolic.svg
|
||||
icons/scalable/status/dino-microphone-symbolic.svg
|
||||
|
@ -53,6 +49,10 @@ set(RESOURCE_LIST
|
|||
icons/scalable/status/dino-video-off-symbolic.svg
|
||||
icons/scalable/status/dino-video-symbolic.svg
|
||||
|
||||
icons/scalable/ui/dino-conversation-list-placeholder-arrow.svg
|
||||
icons/scalable/ui/dino-qr-code-symbolic.svg
|
||||
icons/scalable/ui/dino-party-popper-symbolic.svg
|
||||
|
||||
add_conversation/add_contact_dialog.ui
|
||||
add_conversation/add_groupchat_dialog.ui
|
||||
add_conversation/conference_details_fragment.ui
|
||||
|
@ -103,11 +103,6 @@ compile_gresources(
|
|||
|
||||
unset(MAIN_EXTRA_OPTIONS)
|
||||
unset(MAIN_EXTRA_PACKAGES)
|
||||
# find_package(GDK3)
|
||||
# if(GDK3_WITH_X11)
|
||||
# set(MAIN_EXTRA_OPTIONS ${MAIN_EXTRA_OPTIONS} -D GDK3_WITH_X11)
|
||||
# set(MAIN_EXTRA_PACKAGES ${MAIN_EXTRA_PACKAGES} gdk-x11-3.0)
|
||||
# endif(GDK3_WITH_X11)
|
||||
set(MAIN_EXTRA_OPTIONS ${MAIN_EXTRA_OPTIONS} --vapidir=${CMAKE_CURRENT_SOURCE_DIR}/vapi)
|
||||
|
||||
vala_precompile(MAIN_VALA_C
|
||||
|
@ -226,16 +221,3 @@ install(FILES data/im.dino.Dino.desktop DESTINATION ${DESKTOP_FILE_INSTALL_DIR})
|
|||
install(FILES data/im.dino.Dino.service DESTINATION ${SERVICE_FILE_INSTALL_DIR})
|
||||
install(FILES data/icons/im.dino.Dino.svg DESTINATION ${ICON_INSTALL_DIR}/hicolor/scalable/apps)
|
||||
install(FILES data/icons/im.dino.Dino-symbolic.svg DESTINATION ${ICON_INSTALL_DIR}/hicolor/symbolic/apps)
|
||||
install(FILES
|
||||
data/icons/dino-status-away.svg
|
||||
data/icons/dino-status-chat.svg
|
||||
data/icons/dino-status-dnd.svg
|
||||
data/icons/dino-status-online.svg
|
||||
|
||||
data/icons/dino-changes-prevent-symbolic.svg
|
||||
data/icons/dino-double-tick-symbolic.svg
|
||||
data/icons/dino-qr-code-symbolic.svg
|
||||
data/icons/dino-tick-symbolic.svg
|
||||
DESTINATION
|
||||
${ICON_INSTALL_DIR}/hicolor/scalable/status
|
||||
)
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
<object class="DinoUiAccountComboBox" id="account_combobox">
|
||||
<property name="hexpand">True</property>
|
||||
<property name="width_request">200</property>
|
||||
<property name="visible">True</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">0</property>
|
||||
|
|
|
@ -54,7 +54,6 @@
|
|||
<object class="DinoUiAccountComboBox" id="account_combobox">
|
||||
<property name="hexpand">True</property>
|
||||
<property name="width_request">200</property>
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<interface>
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<template class="DinoUiConferenceDetailsFragment">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkOverlay">
|
||||
<property name="child">
|
||||
|
@ -53,7 +52,6 @@
|
|||
<object class="DinoUiAccountComboBox" id="account_combobox">
|
||||
<property name="hexpand">True</property>
|
||||
<property name="width_request">200</property>
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
<template class="DinoUiSelectJidFragment">
|
||||
<property name="height_request">500</property>
|
||||
<property name="width_request">460</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkGrid">
|
||||
<property name="hexpand">1</property>
|
||||
|
|
|
@ -10,45 +10,38 @@
|
|||
<property name="target-width">350</property>
|
||||
<property name="max-width">350</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="halign">fill</property>
|
||||
<property name="hexpand">true</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="spacing">10</property>
|
||||
<property name="visible">True</property>
|
||||
<style>
|
||||
<class name="call-box"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkImage" id="image">
|
||||
<property name="opacity">0.7</property>
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="title_label">
|
||||
<property name="ellipsize">middle</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0</property>
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="subtitle_label">
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">1</property>
|
||||
<property name="visible">True</property>
|
||||
<attributes>
|
||||
<attribute name="scale" value="0.8"/>
|
||||
</attributes>
|
||||
|
@ -63,10 +56,8 @@
|
|||
<property name="transition-type">slide-down</property>
|
||||
<property name="transition-duration">200</property>
|
||||
<property name="reveal-child">True</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="outer_additional_box">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="incoming_call_box">
|
||||
<property name="halign">end</property>
|
||||
|
@ -80,7 +71,6 @@
|
|||
<child>
|
||||
<object class="GtkButton" id="reject_call_button">
|
||||
<property name="label" translatable="yes">Reject</property>
|
||||
<property name="visible">True</property>
|
||||
<style>
|
||||
<class name="destructive-action"/>
|
||||
</style>
|
||||
|
@ -89,7 +79,6 @@
|
|||
<child>
|
||||
<object class="GtkButton" id="accept_call_button">
|
||||
<property name="label" translatable="yes">Accept</property>
|
||||
<property name="visible">True</property>
|
||||
<style>
|
||||
<class name="suggested-action"/>
|
||||
</style>
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
<template class="DinoUiChatInputView">
|
||||
<property name="hexpand">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="visible">True</property>
|
||||
<style>
|
||||
<class name="dino-chatinput"/>
|
||||
</style>
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
<object class="DinoUiAvatarImage" id="avatar">
|
||||
<property name="height">50</property>
|
||||
<property name="width">50</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="allow_gray">False</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
|
@ -46,7 +45,6 @@
|
|||
<object class="DinoUiUtilEntryLabelHybrid" id="name_hybrid">
|
||||
<property name="xalign">0</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="visible">True</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">0</property>
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
<property name="ellipsize">end</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="visible">True</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="PANGO_WEIGHT_BOLD"/>
|
||||
</attributes>
|
||||
|
@ -18,7 +17,6 @@
|
|||
<object class="GtkLabel" id="time_label">
|
||||
<property name="xalign">0</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="visible">True</property>
|
||||
<attributes>
|
||||
<attribute name="scale" value="0.8"/>
|
||||
</attributes>
|
||||
|
|
|
@ -22,12 +22,10 @@
|
|||
<object class="GtkOverlay">
|
||||
<child>
|
||||
<object class="GtkBox" id="main_event_box">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="DinoUiSizeRequestBox" id="main">
|
||||
<property name="margin-bottom">15</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="size-request-mode">height-for-width</property>
|
||||
</object>
|
||||
</child>
|
||||
|
|
|
@ -50,7 +50,8 @@
|
|||
<child>
|
||||
<object class="GtkImage" id="encrypted_image">
|
||||
<property name="opacity">0.4</property>
|
||||
<property name="pixel-size">14</property>
|
||||
<property name="pixel-size">12</property>
|
||||
<property name="margin-top">2</property>
|
||||
<layout>
|
||||
<property name="column">3</property>
|
||||
<property name="row">0</property>
|
||||
|
@ -60,7 +61,8 @@
|
|||
<child>
|
||||
<object class="GtkImage" id="marked_image">
|
||||
<property name="opacity">0.4</property>
|
||||
<property name="pixel-size">14</property>
|
||||
<property name="pixel-size">13</property>
|
||||
<property name="margin-top">2</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="hexpand">True</property>
|
||||
<layout>
|
||||
|
|
|
@ -1,48 +1,42 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<template class="DinoUiConversationListTitlebar" parent="GtkBox">
|
||||
<property name="hexpand">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="hexpand">0</property>
|
||||
<style>
|
||||
<class name="dino-header-left"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin">5</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="margin-start">5</property>
|
||||
<property name="margin-end">5</property>
|
||||
<property name="margin-top">5</property>
|
||||
<property name="margin-bottom">5</property>
|
||||
<property name="hexpand">1</property>
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="add_button">
|
||||
<property name="tooltip_text" translatable="yes">Start Conversation</property>
|
||||
<property name="relief">none</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip_text" translatable="1">Start Conversation</property>
|
||||
<property name="has-frame">False</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="icon-name">list-add-symbolic</property>
|
||||
<property name="icon-size">1</property>
|
||||
<property name="icon-size">normal</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack_type">start</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="menu_button">
|
||||
<property name="relief">none</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="has-frame">False</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="icon-name">open-menu-symbolic</property>
|
||||
<property name="icon-size">1</property>
|
||||
<property name="icon-size">normal</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack_type">end</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="DinoUiConversationSelectorRow">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkRevealer" id="main_revealer">
|
||||
<property name="transition-type">slide-down</property>
|
||||
<property name="transition-duration">200</property>
|
||||
<property name="reveal-child">True</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">horizontal</property>
|
||||
|
@ -15,24 +13,20 @@
|
|||
<property name="margin-bottom">10</property>
|
||||
<property name="margin-start">7</property>
|
||||
<property name="margin-end">14</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="DinoUiAvatarImage" id="image">
|
||||
<property name="height">35</property>
|
||||
<property name="width">35</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="margin-start">10</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="valign">start</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="name_label">
|
||||
|
@ -41,7 +35,6 @@
|
|||
<property name="hexpand">True</property>
|
||||
<property name="margin-end">7</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -49,7 +42,6 @@
|
|||
<property name="transition-type">slide-right</property>
|
||||
<property name="transition-duration">50</property>
|
||||
<property name="reveal-child">True</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="time_label">
|
||||
<property name="hexpand">False</property>
|
||||
|
@ -66,7 +58,6 @@
|
|||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="valign">end</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">horizontal</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="nick_label">
|
||||
|
@ -101,7 +92,6 @@
|
|||
<property name="transition-type">slide-right</property>
|
||||
<property name="transition-duration">50</property>
|
||||
<property name="reveal-child">True</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="unread_count_label">
|
||||
<property name="vexpand">False</property>
|
||||
|
@ -123,11 +113,9 @@
|
|||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="vexpand">True</property>
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -135,13 +123,11 @@
|
|||
<property name="transition-type">slide-left</property>
|
||||
<property name="transition-duration">100</property>
|
||||
<property name="reveal-child">False</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="x_button">
|
||||
<property name="width-request">27</property>
|
||||
<property name="height-request">27</property>
|
||||
<property name="vexpand">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="margin-start">5</property>
|
||||
<style>
|
||||
<class name="conversation_list_row_xbutton"/>
|
||||
|
@ -152,7 +138,6 @@
|
|||
<object class="GtkImage">
|
||||
<property name="icon-name">window-close-symbolic</property>
|
||||
<property name="icon-size">1</property>
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
@ -162,7 +147,6 @@
|
|||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="vexpand">True</property>
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="DinoUiConversationView">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkOverlay" id="overlay">
|
||||
<child>
|
||||
|
@ -22,7 +21,6 @@
|
|||
<property name="halign">end</property>
|
||||
<property name="valign">end</property>
|
||||
<property name="transition-type">crossfade</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="margin-end">30</property>
|
||||
<property name="margin-bottom">30</property>
|
||||
<child>
|
||||
|
@ -32,7 +30,6 @@
|
|||
<property name="vexpand">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">end</property>
|
||||
<property name="visible">True</property>
|
||||
<style>
|
||||
<class name="circular-button"/>
|
||||
</style>
|
||||
|
@ -40,7 +37,6 @@
|
|||
<object class="GtkImage">
|
||||
<property name="icon-name">go-down-symbolic</property>
|
||||
<property name="icon-size">1</property>
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
@ -51,7 +47,6 @@
|
|||
</child>
|
||||
<child>
|
||||
<object class="DinoUiChatInputView" id="chat_input">
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
@ -65,7 +60,6 @@
|
|||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="opacity">0.7</property>
|
||||
<property name="visible">true</property>
|
||||
<style>
|
||||
<class name="dino-white-overlay"/>
|
||||
</style>
|
||||
|
|
Before Width: | Height: | Size: 456 B After Width: | Height: | Size: 456 B |
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(-154.64 -256.66)">
|
||||
<g transform="matrix(.74332 0 0 .74332 157.02 256.73)" fill="#000000">
|
||||
<path d="m3 9h10c0.554 0 1 0.446 1 1v3c0 0.554-0.446 1-1 1h-10c-0.554 0-1-0.446-1-1v-3c0-0.554 0.446-1 1-1z" overflow="visible"/>
|
||||
<path d="M 7,0 C 7,0 6.291,-0.014 5.553,0.356 4.814,0.725 4,1.666 4,3 V 4.4127188 H 6 V 3 C 6,2.333 6.186,2.275 6.447,2.145 6.71,2.014 7,2 7,2 H 9 C 9,2 9.291,2.014 9.553,2.145 9.814,2.275 10,2.333 10,3 v 8 h 2 V 3 C 12,1.667 11.186,0.725 10.447,0.356 9.71,-0.014 9,0 9,0 Z" font-family="sans-serif" font-weight="400" overflow="visible" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none" white-space="normal"/>
|
||||
<path d="m2 12h12v4h-12z" overflow="visible"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.2 KiB |
|
@ -1,67 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
version="1.1"
|
||||
id="svg7384"
|
||||
height="12">
|
||||
<metadata
|
||||
id="metadata90">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>Gnome Symbolic Icon Theme</dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<title
|
||||
id="title9167">Gnome Symbolic Icon Theme</title>
|
||||
<defs
|
||||
id="defs7386" />
|
||||
<g
|
||||
transform="translate(-181.0002,-241)"
|
||||
style="display:inline"
|
||||
id="layer9">
|
||||
<path
|
||||
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.76307714;marker:none"
|
||||
id="rect4063"
|
||||
d="m 188.13566,241.5 c -1.44483,0 -2.63542,1.19893 -2.63542,2.65384 v 2.65385 h -0.87847 c -0.48668,0 -0.87847,0.39453 -0.87847,0.88462 V 248.16225 253 h 4.39236 1.75695 4.39235 v -4.83775 -0.46994 c 0,-0.49009 -0.39179,-0.88462 -0.87846,-0.88462 h -0.87848 v -2.65385 c 0,-1.45491 -1.19059,-2.65384 -2.63541,-2.65384 z m 0,1.76922 h 1.75695 c 0.50187,0 0.87848,0.37925 0.87848,0.88462 v 2.65385 h -3.5139 v -2.65385 c 0,-0.50537 0.3766,-0.88462 0.87847,-0.88462 z" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-181.0002,-241)"
|
||||
style="display:inline"
|
||||
id="layer10" />
|
||||
<g
|
||||
transform="translate(-181.0002,-241)"
|
||||
id="layer11" />
|
||||
<g
|
||||
transform="translate(-181.0002,-241)"
|
||||
style="display:inline"
|
||||
id="layer13" />
|
||||
<g
|
||||
transform="translate(-181.0002,-241)"
|
||||
id="layer14" />
|
||||
<g
|
||||
transform="translate(-181.0002,-241)"
|
||||
style="display:inline"
|
||||
id="layer15" />
|
||||
<g
|
||||
transform="translate(-181.0002,-241)"
|
||||
style="display:inline"
|
||||
id="g71291" />
|
||||
<g
|
||||
transform="translate(-181.0002,-241)"
|
||||
style="display:inline"
|
||||
id="g4953" />
|
||||
<g
|
||||
transform="translate(-181.0002,-241)"
|
||||
style="display:inline"
|
||||
id="layer12" />
|
||||
</svg>
|
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 673 B After Width: | Height: | Size: 673 B |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 568 B After Width: | Height: | Size: 568 B |
|
@ -2,7 +2,6 @@
|
|||
<interface>
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<template class="DinoUiManageAccountsAccountRow">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkGrid">
|
||||
<property name="margin-start">6</property>
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
</child>
|
||||
<child internal-child="content_area">
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkStack" id="main_stack">
|
||||
<child>
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
<attribute name="action">app.add_chat</attribute>
|
||||
<attribute name="label" translatable="yes">Start Conversation</attribute>
|
||||
</item>
|
||||
</section>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="action">app.add_conference</attribute>
|
||||
<attribute name="label" translatable="yes">Join Channel</attribute>
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
<interface>
|
||||
<object class="GtkBox" id="root">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="DinoUiAvatarImage" id="image">
|
||||
<property name="margin-top">4</property>
|
||||
|
|
|
@ -4,22 +4,18 @@
|
|||
<property name="modal">True</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsSection">
|
||||
<property name="visible">True</property>
|
||||
<property name="section-name">shortcuts</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsGroup">
|
||||
<property name="visible">True</property>
|
||||
<property name="title" translatable="yes">General</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">True</property>
|
||||
<property name="accelerator"><ctrl>T</property>
|
||||
<property name="title" translatable="yes">Start Conversation</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">True</property>
|
||||
<property name="accelerator"><ctrl>G</property>
|
||||
<property name="title" translatable="yes">Join Channel</property>
|
||||
</object>
|
||||
|
@ -28,18 +24,15 @@
|
|||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsGroup">
|
||||
<property name="visible">True</property>
|
||||
<property name="title" translatable="yes">Conversation</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">True</property>
|
||||
<property name="accelerator"><ctrl>F</property>
|
||||
<property name="title" translatable="yes">Search messages</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">True</property>
|
||||
<property name="accelerator"><ctrl>U</property>
|
||||
<property name="title" translatable="yes">Send a file</property>
|
||||
</object>
|
||||
|
@ -48,18 +41,15 @@
|
|||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsGroup">
|
||||
<property name="visible">True</property>
|
||||
<property name="title" translatable="yes">Navigation</property>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">True</property>
|
||||
<property name="accelerator"><ctrl>Tab</property>
|
||||
<property name="title" translatable="yes">Jump to next conversation</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkShortcutsShortcut">
|
||||
<property name="visible">True</property>
|
||||
<property name="accelerator"><ctrl><Shift>Tab</property>
|
||||
<property name="title" translatable="yes">Jump to previous conversation</property>
|
||||
</object>
|
||||
|
|
|
@ -60,7 +60,7 @@ window.dino-main .unread-count-notify {
|
|||
color: @theme_base_color;
|
||||
font-family: monospace;
|
||||
border-radius: 999em;
|
||||
padding: .2em .41em;
|
||||
padding: 0 .35em;
|
||||
}
|
||||
|
||||
window.dino-main .unread-count-notify:backdrop {
|
||||
|
@ -310,7 +310,7 @@ box.dino-input-error label.input-status-highlight-once {
|
|||
background: rgba(255,255,255,0.25);
|
||||
}
|
||||
|
||||
.dino-call-window button.call-mediadevice-settings-button {
|
||||
.dino-call-window menubutton.call-mediadevice-settings-button button.toggle {
|
||||
border-radius: 1000px;
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
|
@ -319,8 +319,8 @@ box.dino-input-error label.input-status-highlight-once {
|
|||
transition-duration: 0;
|
||||
}
|
||||
|
||||
.dino-call-window button.call-mediadevice-settings-button:hover,
|
||||
.dino-call-window button.call-mediadevice-settings-button:checked { /* Effect that makes the button slightly larger on hover :) */
|
||||
.dino-call-window menubutton.call-mediadevice-settings-button button.toggle:hover,
|
||||
.dino-call-window menubutton.call-mediadevice-settings-button button.toggle:checked { /* Effect that makes the button slightly larger on hover :) */
|
||||
border-radius: 1000px;
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
|
@ -328,7 +328,7 @@ box.dino-input-error label.input-status-highlight-once {
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
.dino-call-window .participant-header-bar {
|
||||
.dino-call-window .participant-header-bar .titles {
|
||||
background: none;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
<requires lib="gtk" version="4.0"/>
|
||||
<template class="DinoUiMainWindowPlaceholder">
|
||||
<property name="valign">center</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="box">
|
||||
<property name="orientation">vertical</property>
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace Dino.Ui {
|
|||
public class AddConferenceDialog : Gtk.Dialog {
|
||||
|
||||
private Stack stack = new Stack();
|
||||
private Button cancel_button = new Button() { visible=true };
|
||||
private Button cancel_button = new Button();
|
||||
private Button ok_button;
|
||||
|
||||
private SelectJidFragment select_fragment;
|
||||
|
@ -70,12 +70,12 @@ public class AddConferenceDialog : Gtk.Dialog {
|
|||
|
||||
stack.transition_type = StackTransitionType.SLIDE_LEFT;
|
||||
stack.set_visible_child_name("details");
|
||||
// animate_window_resize();
|
||||
animate_window_resize(details_fragment);
|
||||
}
|
||||
|
||||
private void setup_headerbar() {
|
||||
ok_button = new Button() { can_focus=true, visible=true };
|
||||
ok_button.get_style_context().add_class("suggested-action");
|
||||
ok_button = new Button() { can_focus=true };
|
||||
ok_button.add_css_class("suggested-action");
|
||||
|
||||
if (Util.use_csd()) {
|
||||
HeaderBar header_bar = get_header_bar() as HeaderBar;
|
||||
|
@ -104,18 +104,18 @@ public class AddConferenceDialog : Gtk.Dialog {
|
|||
stream_interactor.get_module(MucManager.IDENTITY).remove_bookmark(conference_row.account, conference_row.bookmark);
|
||||
});
|
||||
|
||||
Box wrap_box = new Box(Orientation.VERTICAL, 0) { visible=true };
|
||||
Box wrap_box = new Box(Orientation.VERTICAL, 0);
|
||||
wrap_box.append(select_fragment);
|
||||
stack.add_named(wrap_box, "select");
|
||||
|
||||
if (!Util.use_csd()) {
|
||||
Box box = new Box(Orientation.HORIZONTAL, 5) { halign=Align.END, margin_bottom=15, margin_start=80, margin_end=80, visible=true };
|
||||
Box box = new Box(Orientation.HORIZONTAL, 5) { halign=Align.END, margin_bottom=15, margin_start=80, margin_end=80 };
|
||||
|
||||
Button ok_button = new Button.with_label(_("Next")) { sensitive=false, halign = Align.END, can_focus=true, visible=true };
|
||||
ok_button.get_style_context().add_class("suggested-action");
|
||||
Button ok_button = new Button.with_label(_("Next")) { sensitive=false, halign = Align.END, can_focus=true };
|
||||
ok_button.add_css_class("suggested-action");
|
||||
ok_button.clicked.connect(on_next_button_clicked);
|
||||
select_fragment.notify["done"].connect(() => { ok_button.sensitive = select_fragment.done; });
|
||||
Button cancel_button = new Button.with_label(_("Cancel")) { halign=Align.START, visible=true };
|
||||
Button cancel_button = new Button.with_label(_("Cancel")) { halign=Align.START };
|
||||
cancel_button.clicked.connect(on_cancel);
|
||||
box.append(cancel_button);
|
||||
box.append(ok_button);
|
||||
|
@ -129,18 +129,18 @@ public class AddConferenceDialog : Gtk.Dialog {
|
|||
details_fragment = new ConferenceDetailsFragment(stream_interactor) { ok_button=ok_button };
|
||||
details_fragment.joined.connect(() => this.close());
|
||||
|
||||
Box wrap_box = new Box(Orientation.VERTICAL, 0) { visible=true };
|
||||
Box wrap_box = new Box(Orientation.VERTICAL, 0);
|
||||
wrap_box.append(details_fragment);
|
||||
|
||||
if (!Util.use_csd()) {
|
||||
Box box = new Box(Orientation.HORIZONTAL, 5) { halign=Align.END, margin_bottom=15, margin_start=80, margin_end=80, visible=true };
|
||||
Box box = new Box(Orientation.HORIZONTAL, 5) { halign=Align.END, margin_bottom=15, margin_start=80, margin_end=80 };
|
||||
|
||||
Button ok_button = new Button.with_label(_("Join")) { halign = Align.END, can_focus=true, visible=true };
|
||||
ok_button.get_style_context().add_class("suggested-action");
|
||||
Button ok_button = new Button.with_label(_("Join")) { halign = Align.END, can_focus=true };
|
||||
ok_button.add_css_class("suggested-action");
|
||||
details_fragment.notify["done"].connect(() => { ok_button.sensitive = select_fragment.done; });
|
||||
details_fragment.ok_button = ok_button;
|
||||
|
||||
Button cancel_button = new Button.with_label(_("Back")) { halign=Align.START, visible=true };
|
||||
Button cancel_button = new Button.with_label(_("Back")) { halign=Align.START };
|
||||
cancel_button.clicked.connect(show_jid_add_view);
|
||||
box.append(cancel_button);
|
||||
box.append(ok_button);
|
||||
|
@ -180,21 +180,18 @@ public class AddConferenceDialog : Gtk.Dialog {
|
|||
close();
|
||||
}
|
||||
|
||||
private void animate_window_resize() {
|
||||
private void animate_window_resize(Widget widget) {
|
||||
int curr_height = get_size(Orientation.VERTICAL);
|
||||
int curr_width = get_size(Orientation.HORIZONTAL);
|
||||
var natural_size = new Requisition();
|
||||
stack.get_preferred_size(null, out natural_size);
|
||||
var natural_size = Requisition();
|
||||
widget.get_preferred_size(null, out natural_size);
|
||||
int difference = natural_size.height - curr_height;
|
||||
Timer timer = new Timer();
|
||||
Timeout.add((int) (stack.transition_duration / 30),
|
||||
() => {
|
||||
Timeout.add((int) (stack.transition_duration / 30), () => {
|
||||
ulong microsec;
|
||||
timer.elapsed(out microsec);
|
||||
ulong millisec = microsec / 1000;
|
||||
double partial = double.min(1, (double) millisec / stack.transition_duration);
|
||||
var a = this.list_toplevels().nth_data(0);
|
||||
set_size_request(curr_width, (int) (curr_height + difference * partial));
|
||||
default_height = (int) (curr_height + difference * partial);
|
||||
return millisec < stack.transition_duration;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ protected class AddGroupchatDialog : Gtk.Dialog {
|
|||
Object(use_header_bar : 1);
|
||||
this.stream_interactor = stream_interactor;
|
||||
ok_button.label = _("Add");
|
||||
ok_button.get_style_context().add_class("suggested-action"); // TODO why doesn't it work in XML
|
||||
ok_button.add_css_class("suggested-action"); // TODO why doesn't it work in XML
|
||||
accounts_stack.set_visible_child_name("combobox");
|
||||
account_combobox.initialize(stream_interactor);
|
||||
|
||||
|
|
|
@ -20,10 +20,6 @@ protected class ConferenceList {
|
|||
public ConferenceList(StreamInteractor stream_interactor) {
|
||||
this.stream_interactor = stream_interactor;
|
||||
|
||||
// list_box.set_filter_func(filter);
|
||||
list_box.set_header_func(header);
|
||||
// list_box.set_sort_func(sort);
|
||||
|
||||
stream_interactor.get_module(MucManager.IDENTITY).bookmarks_updated.connect((account, conferences) => {
|
||||
lists[account] = conferences;
|
||||
refresh_conferences();
|
||||
|
@ -57,7 +53,12 @@ protected class ConferenceList {
|
|||
}
|
||||
|
||||
public void refresh_conferences() {
|
||||
// @foreach((widget) => { remove(widget); });
|
||||
foreach (Account account in widgets.keys) {
|
||||
foreach (Jid jid in widgets[account].keys) {
|
||||
remove_conference(account, jid);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Account account in lists.keys) {
|
||||
foreach (Conference conference in lists[account]) {
|
||||
add_conference(account, conference);
|
||||
|
@ -74,12 +75,6 @@ protected class ConferenceList {
|
|||
refresh_conferences();
|
||||
}
|
||||
|
||||
private void header(ListBoxRow row, ListBoxRow? before_row) {
|
||||
if (row.get_header() == null && before_row != null) {
|
||||
row.set_header(new Separator(Orientation.HORIZONTAL));
|
||||
}
|
||||
}
|
||||
|
||||
public ListBox get_list_box() {
|
||||
return list_box;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ public class ListRow : Widget {
|
|||
via_label = (Label) builder.get_object("via_label");
|
||||
|
||||
this.layout_manager = new BinLayout();
|
||||
outer_grid.insert_after(this, null);
|
||||
outer_grid.set_parent(this);
|
||||
}
|
||||
|
||||
public ListRow() {}
|
||||
|
@ -47,6 +47,10 @@ public class ListRow : Widget {
|
|||
name_label.label = display_name;
|
||||
image.set_conversation(stream_interactor, conv);
|
||||
}
|
||||
|
||||
public override void dispose() {
|
||||
outer_grid.unparent();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,10 +20,6 @@ protected class RosterList {
|
|||
this.stream_interactor = stream_interactor;
|
||||
this.accounts = accounts;
|
||||
|
||||
// set_filter_func(filter);
|
||||
list_box.set_header_func(header);
|
||||
// set_sort_func(sort);
|
||||
|
||||
handler_ids += stream_interactor.get_module(RosterManager.IDENTITY).removed_roster_item.connect( (account, jid, roster_item) => {
|
||||
if (accounts.contains(account)) {
|
||||
on_removed_roster_item(account, jid, roster_item);
|
||||
|
@ -64,12 +60,6 @@ protected class RosterList {
|
|||
}
|
||||
}
|
||||
|
||||
private void header(ListBoxRow row, ListBoxRow? before_row) {
|
||||
if (row.get_header() == null && before_row != null) {
|
||||
row.set_header(new Separator(Orientation.HORIZONTAL));
|
||||
}
|
||||
}
|
||||
|
||||
public ListBox get_list_box() {
|
||||
return list_box;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ public class SelectContactDialog : Gtk.Dialog {
|
|||
cancel_button.visible = true;
|
||||
|
||||
ok_button = new Button();
|
||||
ok_button.get_style_context().add_class("suggested-action");
|
||||
ok_button.add_css_class("suggested-action");
|
||||
ok_button.sensitive = false;
|
||||
ok_button.visible = true;
|
||||
|
||||
|
@ -51,7 +51,7 @@ public class SelectContactDialog : Gtk.Dialog {
|
|||
header_bar.pack_start(cancel_button);
|
||||
header_bar.pack_end(ok_button);
|
||||
} else {
|
||||
Box box = new Box(Orientation.HORIZONTAL, 5) { halign=Align.END, margin_bottom=15, margin_start=80, margin_end=80, visible=true };
|
||||
Box box = new Box(Orientation.HORIZONTAL, 5) { halign=Align.END, margin_bottom=15, margin_start=80, margin_end=80 };
|
||||
|
||||
cancel_button.halign = Align.START;
|
||||
ok_button.halign = Align.END;
|
||||
|
|
|
@ -23,7 +23,7 @@ public class SelectJidFragment : Gtk.Box {
|
|||
|
||||
private StreamInteractor stream_interactor;
|
||||
private Gee.List<Account> accounts;
|
||||
private ArrayList<AddListRow> added_rows = new ArrayList<AddListRow>();
|
||||
private ArrayList<Widget> added_rows = new ArrayList<Widget>();
|
||||
|
||||
private ListBox list;
|
||||
private string[]? filter_values;
|
||||
|
@ -39,6 +39,7 @@ public class SelectJidFragment : Gtk.Box {
|
|||
|
||||
list.set_sort_func(sort);
|
||||
list.set_filter_func(filter);
|
||||
list.set_header_func(header);
|
||||
list.row_selected.connect(check_buttons_active);
|
||||
list.row_selected.connect(() => { done = true; }); // just for notifying
|
||||
entry.changed.connect(() => { set_filter(entry.text); });
|
||||
|
@ -49,7 +50,7 @@ public class SelectJidFragment : Gtk.Box {
|
|||
public void set_filter(string str) {
|
||||
if (entry.text != str) entry.text = str;
|
||||
|
||||
foreach (AddListRow row in added_rows) list.remove(row);
|
||||
foreach (Widget row in added_rows) list.remove(row);
|
||||
added_rows.clear();
|
||||
|
||||
filter_values = str == "" ? null : str.split(" ");
|
||||
|
@ -59,9 +60,10 @@ public class SelectJidFragment : Gtk.Box {
|
|||
Jid parsed_jid = new Jid(str);
|
||||
if (parsed_jid != null && parsed_jid.localpart != null) {
|
||||
foreach (Account account in accounts) {
|
||||
AddListRow row = new AddListRow(stream_interactor, parsed_jid, account);
|
||||
list.append(row);
|
||||
added_rows.add(row);
|
||||
var list_row = new Gtk.ListBoxRow();
|
||||
list_row.set_child(new AddListRow(stream_interactor, parsed_jid, account));
|
||||
list.append(list_row);
|
||||
added_rows.add(list_row);
|
||||
}
|
||||
}
|
||||
} catch (InvalidJidError ignored) {
|
||||
|
@ -108,6 +110,12 @@ public class SelectJidFragment : Gtk.Box {
|
|||
return true;
|
||||
}
|
||||
|
||||
private void header(ListBoxRow row, ListBoxRow? before_row) {
|
||||
if (row.get_header() == null && before_row != null) {
|
||||
row.set_header(new Separator(Orientation.HORIZONTAL));
|
||||
}
|
||||
}
|
||||
|
||||
private class AddListRow : ListRow {
|
||||
|
||||
public AddListRow(StreamInteractor stream_interactor, Jid jid, Account account) {
|
||||
|
|
|
@ -203,11 +203,6 @@ public class Dino.Ui.Application : Gtk.Application, Dino.Application {
|
|||
Builder builder = new Builder.from_resource("/im/dino/Dino/shortcuts.ui");
|
||||
ShortcutsWindow dialog = (ShortcutsWindow) builder.get_object("shortcuts-window");
|
||||
if (!use_csd()) {
|
||||
// Hack to prevent CRITICAL in Gtk when trying to destroy non-existant headerbar
|
||||
Widget shortcuts_hack = dialog.get_titlebar();
|
||||
// dialog.destroy.connect_after(() => {
|
||||
// shortcuts_hack = null;
|
||||
// });
|
||||
dialog.set_titlebar(null);
|
||||
}
|
||||
dialog.title = _("Keyboard Shortcuts");
|
||||
|
@ -292,12 +287,6 @@ public class Dino.Ui.Application : Gtk.Application, Dino.Application {
|
|||
dialog.copyright = "Copyright © 2016-2022 - Dino Team";
|
||||
dialog.license_type = License.GPL_3_0;
|
||||
|
||||
// dialog.response.connect((response_id) => {
|
||||
// if (response_id == Gtk.ResponseType.CANCEL || response_id == Gtk.ResponseType.DELETE_EVENT) {
|
||||
// dialog.destroy();
|
||||
// }
|
||||
// });
|
||||
|
||||
if (!use_csd()) {
|
||||
dialog.set_titlebar(null);
|
||||
}
|
||||
|
@ -308,7 +297,7 @@ public class Dino.Ui.Application : Gtk.Application, Dino.Application {
|
|||
Dialog dialog = new Dialog.with_buttons(_("Join Channel"), window, Gtk.DialogFlags.MODAL | Gtk.DialogFlags.USE_HEADER_BAR, _("Join"), ResponseType.OK, _("Cancel"), ResponseType.CANCEL);
|
||||
dialog.modal = true;
|
||||
Button ok_button = dialog.get_widget_for_response(ResponseType.OK) as Button;
|
||||
ok_button.get_style_context().add_class("suggested-action");
|
||||
ok_button.add_css_class("suggested-action");
|
||||
ConferenceDetailsFragment conference_fragment = new ConferenceDetailsFragment(stream_interactor) { ok_button=ok_button };
|
||||
conference_fragment.jid = jid;
|
||||
if (account != null) {
|
||||
|
|
|
@ -24,7 +24,7 @@ public class AvatarImage : Widget {
|
|||
|
||||
public AvatarImage() {
|
||||
can_focus = false;
|
||||
get_style_context().add_class("avatar");
|
||||
add_css_class("avatar");
|
||||
}
|
||||
|
||||
public override void dispose() {
|
||||
|
@ -51,7 +51,6 @@ public class AvatarImage : Widget {
|
|||
}
|
||||
|
||||
public bool draw(Cairo.Context ctx_in) {
|
||||
if (conversation == null || jids == null) return false;
|
||||
Cairo.Context ctx = ctx_in;
|
||||
int width = this.width, height = this.height, base_factor = 1;
|
||||
if (use_image_surface == -1) {
|
||||
|
|
|
@ -14,7 +14,7 @@ public class Dino.Ui.AudioSettingsPopover : Gtk.Popover {
|
|||
private HashMap<ListBoxRow, Plugins.MediaDevice> row_speaker_device = new HashMap<ListBoxRow, Plugins.MediaDevice>();
|
||||
|
||||
public AudioSettingsPopover() {
|
||||
Box box = new Box(Orientation.VERTICAL, 15) { visible=true };
|
||||
Box box = new Box(Orientation.VERTICAL, 15);
|
||||
box.append(create_microphone_box());
|
||||
box.append(create_speaker_box());
|
||||
|
||||
|
@ -25,19 +25,19 @@ public class Dino.Ui.AudioSettingsPopover : Gtk.Popover {
|
|||
Plugins.VideoCallPlugin call_plugin = Dino.Application.get_default().plugin_registry.video_call_plugin;
|
||||
Gee.List<Plugins.MediaDevice> devices = call_plugin.get_devices("audio", false);
|
||||
|
||||
Box micro_box = new Box(Orientation.VERTICAL, 10) { visible=true };
|
||||
micro_box.append(new Label("<b>" + _("Microphones") + "</b>") { use_markup=true, xalign=0, visible=true, can_focus=true /* grab initial focus*/ });
|
||||
Box micro_box = new Box(Orientation.VERTICAL, 10);
|
||||
micro_box.append(new Label("<b>" + _("Microphones") + "</b>") { use_markup=true, xalign=0, can_focus=true /* grab initial focus*/ });
|
||||
|
||||
if (devices.size == 0) {
|
||||
micro_box.append(new Label(_("No microphone found.")));
|
||||
} else {
|
||||
ListBox micro_list_box = new ListBox() { activate_on_single_click=true, selection_mode=SelectionMode.SINGLE, visible=true };
|
||||
ListBox micro_list_box = new ListBox() { activate_on_single_click=true, selection_mode=SelectionMode.SINGLE };
|
||||
micro_list_box.set_header_func(listbox_header_func);
|
||||
Frame micro_frame = new Frame(null) { visible=true };
|
||||
Frame micro_frame = new Frame(null);
|
||||
micro_frame.set_child(micro_list_box);
|
||||
foreach (Plugins.MediaDevice device in devices) {
|
||||
Label display_name_label = new Label(device.display_name) { xalign=0, visible=true };
|
||||
Image image = new Image.from_icon_name("object-select-symbolic") { visible=true };
|
||||
Label display_name_label = new Label(device.display_name) { xalign=0 };
|
||||
Image image = new Image.from_icon_name("object-select-symbolic");
|
||||
if (current_microphone_device == null || current_microphone_device.id != device.id) {
|
||||
image.opacity = 0;
|
||||
}
|
||||
|
@ -48,19 +48,19 @@ public class Dino.Ui.AudioSettingsPopover : Gtk.Popover {
|
|||
image.opacity = 1;
|
||||
}
|
||||
});
|
||||
Box device_box = new Box(Orientation.HORIZONTAL, 0) { spacing=7, visible=true };
|
||||
Box device_box = new Box(Orientation.HORIZONTAL, 0) { spacing=7 };
|
||||
device_box.append(image);
|
||||
Box label_box = new Box(Orientation.VERTICAL, 0) { visible = true };
|
||||
Box label_box = new Box(Orientation.VERTICAL, 0);
|
||||
label_box.append(display_name_label);
|
||||
if (device.detail_name != null) {
|
||||
Label detail_name_label = new Label(device.detail_name) { xalign=0, visible=true };
|
||||
detail_name_label.get_style_context().add_class("dim-label");
|
||||
Label detail_name_label = new Label(device.detail_name) { xalign=0 };
|
||||
detail_name_label.add_css_class("dim-label");
|
||||
detail_name_label.attributes = new Pango.AttrList();
|
||||
detail_name_label.attributes.insert(Pango.attr_scale_new(0.8));
|
||||
label_box.append(detail_name_label);
|
||||
}
|
||||
device_box.append(label_box);
|
||||
ListBoxRow list_box_row = new ListBoxRow() { visible=true };
|
||||
ListBoxRow list_box_row = new ListBoxRow();
|
||||
list_box_row.set_child(device_box);
|
||||
micro_list_box.append(list_box_row);
|
||||
|
||||
|
@ -81,22 +81,22 @@ public class Dino.Ui.AudioSettingsPopover : Gtk.Popover {
|
|||
Plugins.VideoCallPlugin call_plugin = Dino.Application.get_default().plugin_registry.video_call_plugin;
|
||||
Gee.List<Plugins.MediaDevice> devices = call_plugin.get_devices("audio", true);
|
||||
|
||||
Box speaker_box = new Box(Orientation.VERTICAL, 10) { visible=true };
|
||||
speaker_box.append(new Label("<b>" + _("Speakers") +"</b>") { use_markup=true, xalign=0, visible=true });
|
||||
Box speaker_box = new Box(Orientation.VERTICAL, 10);
|
||||
speaker_box.append(new Label("<b>" + _("Speakers") +"</b>") { use_markup=true, xalign=0 });
|
||||
|
||||
if (devices.size == 0) {
|
||||
speaker_box.append(new Label(_("No speaker found.")));
|
||||
} else {
|
||||
ListBox speaker_list_box = new ListBox() { activate_on_single_click=true, selection_mode=SelectionMode.SINGLE, visible=true };
|
||||
ListBox speaker_list_box = new ListBox() { activate_on_single_click=true, selection_mode=SelectionMode.SINGLE };
|
||||
speaker_list_box.set_header_func(listbox_header_func);
|
||||
speaker_list_box.row_selected.connect((row) => {
|
||||
|
||||
});
|
||||
Frame speaker_frame = new Frame(null) { visible=true };
|
||||
Frame speaker_frame = new Frame(null);
|
||||
speaker_frame.set_child(speaker_list_box);
|
||||
foreach (Plugins.MediaDevice device in devices) {
|
||||
Label display_name_label = new Label(device.display_name) { xalign=0, visible=true };
|
||||
Image image = new Image.from_icon_name("object-select-symbolic") { visible=true };
|
||||
Label display_name_label = new Label(device.display_name) { xalign=0 };
|
||||
Image image = new Image.from_icon_name("object-select-symbolic");
|
||||
if (current_speaker_device == null || current_speaker_device.id != device.id) {
|
||||
image.opacity = 0;
|
||||
}
|
||||
|
@ -107,19 +107,19 @@ public class Dino.Ui.AudioSettingsPopover : Gtk.Popover {
|
|||
image.opacity = 1;
|
||||
}
|
||||
});
|
||||
Box device_box = new Box(Orientation.HORIZONTAL, 0) { spacing=7, visible=true };
|
||||
Box device_box = new Box(Orientation.HORIZONTAL, 0) { spacing=7 };
|
||||
device_box.append(image);
|
||||
Box label_box = new Box(Orientation.VERTICAL, 0) { visible = true };
|
||||
label_box.append(display_name_label);
|
||||
if (device.detail_name != null) {
|
||||
Label detail_name_label = new Label(device.detail_name) { xalign=0, visible=true };
|
||||
detail_name_label.get_style_context().add_class("dim-label");
|
||||
Label detail_name_label = new Label(device.detail_name) { xalign=0 };
|
||||
detail_name_label.add_css_class("dim-label");
|
||||
detail_name_label.attributes = new Pango.AttrList();
|
||||
detail_name_label.attributes.insert(Pango.attr_scale_new(0.8));
|
||||
label_box.append(detail_name_label);
|
||||
}
|
||||
device_box.append(label_box);
|
||||
ListBoxRow list_box_row = new ListBoxRow() { visible=true };
|
||||
ListBoxRow list_box_row = new ListBoxRow();
|
||||
list_box_row.set_child(device_box);
|
||||
speaker_list_box.append(list_box_row);
|
||||
|
||||
|
|
|
@ -11,52 +11,54 @@ public class Dino.Ui.CallBottomBar : Gtk.Box {
|
|||
|
||||
public string counterpart_display_name { get; set; }
|
||||
|
||||
private Button audio_button = new Button() { height_request=45, width_request=45, halign=Align.START, valign=Align.START, visible=true };
|
||||
private Overlay audio_button_overlay = new Overlay() { visible=true };
|
||||
private Button audio_button = new Button() { height_request=45, width_request=45, halign=Align.START, valign=Align.START };
|
||||
private Overlay audio_button_overlay = new Overlay();
|
||||
private Image audio_image = new Image() { pixel_size=22 };
|
||||
private MenuButton audio_settings_button = new MenuButton() { icon_name="go-up-symbolic", halign=Align.END, valign=Align.END };
|
||||
private MenuButton audio_settings_button = new MenuButton() { halign=Align.END, valign=Align.END };
|
||||
public AudioSettingsPopover? audio_settings_popover;
|
||||
|
||||
private Button video_button = new Button() { height_request=45, width_request=45, halign=Align.START, valign=Align.START, visible=true };
|
||||
private Overlay video_button_overlay = new Overlay() { visible=true };
|
||||
private Button video_button = new Button() { height_request=45, width_request=45, halign=Align.START, valign=Align.START };
|
||||
private Overlay video_button_overlay = new Overlay();
|
||||
private Image video_image = new Image() { pixel_size=22 };
|
||||
private MenuButton video_settings_button = new MenuButton() { icon_name="go-up-symbolic", halign=Align.END, valign=Align.END };
|
||||
private MenuButton video_settings_button = new MenuButton() { halign=Align.END, valign=Align.END };
|
||||
public VideoSettingsPopover? video_settings_popover;
|
||||
|
||||
private Label label = new Label("") { halign=Align.CENTER, valign=Align.CENTER, wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR, hexpand=true, visible=true };
|
||||
private Stack stack = new Stack() { visible=true };
|
||||
private Label label = new Label("") { halign=Align.CENTER, valign=Align.CENTER, wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR, hexpand=true };
|
||||
private Stack stack = new Stack();
|
||||
|
||||
public CallBottomBar() {
|
||||
Object(orientation:Orientation.HORIZONTAL, spacing:0);
|
||||
|
||||
Box main_buttons = new Box(Orientation.HORIZONTAL, 20) { margin_start=40, margin_end=40, margin_bottom=20, margin_top=20, halign=Align.CENTER, hexpand=true, visible=true };
|
||||
Box main_buttons = new Box(Orientation.HORIZONTAL, 20) { margin_start=40, margin_end=40, margin_bottom=20, margin_top=20, halign=Align.CENTER, hexpand=true };
|
||||
|
||||
audio_button.set_child(audio_image);
|
||||
audio_button.get_style_context().add_class("call-button");
|
||||
audio_button.add_css_class("call-button");
|
||||
audio_button.clicked.connect(() => { audio_enabled = !audio_enabled; });
|
||||
audio_button.margin_end = audio_button.margin_bottom = 5; // space for the small settings button
|
||||
audio_button_overlay.set_child(audio_button);
|
||||
audio_button_overlay.add_overlay(audio_settings_button);
|
||||
audio_settings_button.get_style_context().add_class("call-mediadevice-settings-button");
|
||||
audio_settings_button.set_child(new Image.from_icon_name("go-up-symbolic") { pixel_size=10 });
|
||||
audio_settings_button.add_css_class("call-mediadevice-settings-button");
|
||||
main_buttons.append(audio_button_overlay);
|
||||
|
||||
video_button.set_child(video_image);
|
||||
video_button.get_style_context().add_class("call-button");
|
||||
video_button.add_css_class("call-button");
|
||||
video_button.clicked.connect(() => { video_enabled = !video_enabled; });
|
||||
video_button.margin_end = video_button.margin_bottom = 5;
|
||||
video_button_overlay.set_child(video_button);
|
||||
video_button_overlay.add_overlay(video_settings_button);
|
||||
video_settings_button.get_style_context().add_class("call-mediadevice-settings-button");
|
||||
video_settings_button.set_child(new Image.from_icon_name("go-up-symbolic") { pixel_size=10 });
|
||||
video_settings_button.add_css_class("call-mediadevice-settings-button");
|
||||
main_buttons.append(video_button_overlay);
|
||||
|
||||
Button button_hang = new Button() { height_request=45, width_request=45, halign=Align.START, valign=Align.START, visible=true };
|
||||
Button button_hang = new Button() { height_request=45, width_request=45, halign=Align.START, valign=Align.START };
|
||||
button_hang.set_child(new Image() { icon_name="dino-phone-hangup-symbolic", pixel_size=22 });
|
||||
button_hang.get_style_context().add_class("call-button");
|
||||
button_hang.get_style_context().add_class("destructive-action");
|
||||
button_hang.add_css_class("call-button");
|
||||
button_hang.add_css_class("destructive-action");
|
||||
button_hang.clicked.connect(() => hang_up());
|
||||
main_buttons.append(button_hang);
|
||||
|
||||
label.get_style_context().add_class("text-no-controls");
|
||||
label.add_css_class("text-no-controls");
|
||||
|
||||
stack.add_named(main_buttons, "control-buttons");
|
||||
stack.add_named(label, "label");
|
||||
|
@ -71,7 +73,7 @@ public class Dino.Ui.CallBottomBar : Gtk.Box {
|
|||
on_audio_enabled_changed();
|
||||
on_video_enabled_changed();
|
||||
|
||||
this.get_style_context().add_class("call-bottom-bar");
|
||||
this.add_css_class("call-bottom-bar");
|
||||
}
|
||||
|
||||
public AudioSettingsPopover? show_audio_device_choices(bool show) {
|
||||
|
@ -112,25 +114,25 @@ public class Dino.Ui.CallBottomBar : Gtk.Box {
|
|||
public void on_audio_enabled_changed() {
|
||||
if (audio_enabled) {
|
||||
audio_image.icon_name = "dino-microphone-symbolic";
|
||||
audio_button.get_style_context().add_class("white-button");
|
||||
audio_button.get_style_context().remove_class("transparent-white-button");
|
||||
audio_button.add_css_class("white-button");
|
||||
audio_button.remove_css_class("transparent-white-button");
|
||||
} else {
|
||||
audio_image.icon_name = "dino-microphone-off-symbolic";
|
||||
audio_button.get_style_context().remove_class("white-button");
|
||||
audio_button.get_style_context().add_class("transparent-white-button");
|
||||
audio_button.remove_css_class("white-button");
|
||||
audio_button.add_css_class("transparent-white-button");
|
||||
}
|
||||
}
|
||||
|
||||
public void on_video_enabled_changed() {
|
||||
if (video_enabled) {
|
||||
video_image.icon_name = "dino-video-symbolic";
|
||||
video_button.get_style_context().add_class("white-button");
|
||||
video_button.get_style_context().remove_class("transparent-white-button");
|
||||
video_button.add_css_class("white-button");
|
||||
video_button.remove_css_class("transparent-white-button");
|
||||
|
||||
} else {
|
||||
video_image.icon_name = "dino-video-off-symbolic";
|
||||
video_button.get_style_context().remove_class("white-button");
|
||||
video_button.get_style_context().add_class("transparent-white-button");
|
||||
video_button.remove_css_class("white-button");
|
||||
video_button.add_css_class("transparent-white-button");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,6 +142,7 @@ public class Dino.Ui.CallBottomBar : Gtk.Box {
|
|||
}
|
||||
|
||||
public bool is_menu_active() {
|
||||
return video_settings_button.popover.visible || audio_settings_button.popover.visible; // TODO gtk4 does this work? check for null?
|
||||
return (video_settings_button.popover != null && video_settings_button.popover.visible) ||
|
||||
(audio_settings_button.popover != null && audio_settings_button.popover.visible);
|
||||
}
|
||||
}
|
|
@ -4,10 +4,10 @@ namespace Dino.Ui {
|
|||
|
||||
public class CallConnectionDetailsWindow : Gtk.Window {
|
||||
|
||||
public Box box = new Box(Orientation.VERTICAL, 15) { halign=Align.CENTER, valign=Align.CENTER, visible=true };
|
||||
public Box box = new Box(Orientation.VERTICAL, 15) { halign=Align.CENTER, valign=Align.CENTER };
|
||||
|
||||
private bool video_added = false;
|
||||
private CallContentDetails audio_details = new CallContentDetails("Audio") { visible=true };
|
||||
private CallContentDetails audio_details = new CallContentDetails("Audio");
|
||||
private CallContentDetails video_details = new CallContentDetails("Video");
|
||||
|
||||
public CallConnectionDetailsWindow() {
|
||||
|
@ -36,24 +36,24 @@ namespace Dino.Ui {
|
|||
|
||||
public class CallContentDetails : Gtk.Grid {
|
||||
|
||||
public Label rtp_title = new Label("RTP") { xalign=0, visible=true };
|
||||
public Label rtcp_title = new Label("RTCP") { xalign=0, visible=true };
|
||||
public Label target_recv_title = new Label("Target receive bitrate") { xalign=0, visible=true };
|
||||
public Label target_send_title = new Label("Target send bitrate") { xalign=0, visible=true };
|
||||
public Label rtp_title = new Label("RTP") { xalign=0 };
|
||||
public Label rtcp_title = new Label("RTCP") { xalign=0 };
|
||||
public Label target_recv_title = new Label("Target receive bitrate") { xalign=0 };
|
||||
public Label target_send_title = new Label("Target send bitrate") { xalign=0 };
|
||||
|
||||
public Label rtp_ready = new Label("?") { xalign=0, visible=true };
|
||||
public Label rtcp_ready = new Label("?") { xalign=0, visible=true };
|
||||
public Label sent_bps = new Label("?") { use_markup=true, xalign=0, visible=true };
|
||||
public Label recv_bps = new Label("?") { use_markup=true, xalign=0, visible=true };
|
||||
public Label codec = new Label("?") { xalign=0, visible=true };
|
||||
public Label target_receive_bitrate = new Label("n/a") { use_markup=true, xalign=0, visible=true };
|
||||
public Label target_send_bitrate = new Label("n/a") { use_markup=true, xalign=0, visible=true };
|
||||
public Label rtp_ready = new Label("?") { xalign=0 };
|
||||
public Label rtcp_ready = new Label("?") { xalign=0 };
|
||||
public Label sent_bps = new Label("?") { use_markup=true, xalign=0 };
|
||||
public Label recv_bps = new Label("?") { use_markup=true, xalign=0 };
|
||||
public Label codec = new Label("?") { xalign=0 };
|
||||
public Label target_receive_bitrate = new Label("n/a") { use_markup=true, xalign=0 };
|
||||
public Label target_send_bitrate = new Label("n/a") { use_markup=true, xalign=0 };
|
||||
|
||||
private PeerContentInfo? prev_info = null;
|
||||
private int row_at = 0;
|
||||
|
||||
public CallContentDetails(string headline) {
|
||||
attach(new Label("<b>%s</b>".printf(headline)) { use_markup=true, xalign=0, visible=true }, 0, row_at++, 1, 1);
|
||||
attach(new Label("<b>%s</b>".printf(headline)) { use_markup=true, xalign=0 }, 0, row_at++, 1, 1);
|
||||
attach(rtp_title, 0, row_at, 1, 1);
|
||||
attach(rtp_ready, 1, row_at++, 1, 1);
|
||||
attach(rtcp_title, 0, row_at, 1, 1);
|
||||
|
@ -104,7 +104,7 @@ namespace Dino.Ui {
|
|||
}
|
||||
|
||||
private void put_row(string label) {
|
||||
attach(new Label(label) { xalign=0, visible=true }, 0, row_at, 1, 1);
|
||||
attach(new Label(label) { xalign=0 }, 0, row_at, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ using Dino.Entities;
|
|||
using Gtk;
|
||||
using Pango;
|
||||
|
||||
public class Dino.Ui.CallEncryptionButtonController {
|
||||
public class Dino.Ui.CallEncryptionButtonController : Object {
|
||||
|
||||
private bool has_been_set = false;
|
||||
public bool controls_active { get; set; default=false; }
|
||||
|
@ -21,10 +21,10 @@ public class Dino.Ui.CallEncryptionButtonController {
|
|||
public void set_icon(bool encrypted, string? icon_name) {
|
||||
if (encrypted) {
|
||||
button.icon_name = icon_name ?? "changes-prevent-symbolic";
|
||||
button.get_style_context().remove_class("unencrypted");
|
||||
button.remove_css_class("unencrypted");
|
||||
} else {
|
||||
button.icon_name = icon_name ?? "changes-allow-symbolic";
|
||||
button.get_style_context().add_class("unencrypted");
|
||||
button.add_css_class("unencrypted");
|
||||
}
|
||||
has_been_set = true;
|
||||
update_opacity();
|
||||
|
@ -35,23 +35,23 @@ public class Dino.Ui.CallEncryptionButtonController {
|
|||
button.set_popover(popover);
|
||||
|
||||
if (audio_encryption == null) {
|
||||
popover.set_child(new Label("This call is unencrypted.") { visible=true } );
|
||||
popover.set_child(new Label("This call is unencrypted.") );
|
||||
return;
|
||||
}
|
||||
if (title != null && !show_keys) {
|
||||
popover.set_child(new Label(title) { use_markup=true, visible=true } );
|
||||
popover.set_child(new Label(title) { use_markup=true } );
|
||||
return;
|
||||
}
|
||||
|
||||
Box box = new Box(Orientation.VERTICAL, 10) { visible=true };
|
||||
box.append(new Label("<b>%s</b>".printf(title ?? "This call is end-to-end encrypted.")) { use_markup=true, xalign=0, visible=true });
|
||||
Box box = new Box(Orientation.VERTICAL, 10);
|
||||
box.append(new Label("<b>%s</b>".printf(title ?? "This call is end-to-end encrypted.")) { use_markup=true, xalign=0 });
|
||||
|
||||
if (video_encryption == null) {
|
||||
box.append(create_media_encryption_grid(audio_encryption));
|
||||
} else {
|
||||
box.append(new Label("<b>Audio</b>") { use_markup=true, xalign=0, visible=true });
|
||||
box.append(new Label("<b>Audio</b>") { use_markup=true, xalign=0 });
|
||||
box.append(create_media_encryption_grid(audio_encryption));
|
||||
box.append(new Label("<b>Video</b>") { use_markup=true, xalign=0, visible=true });
|
||||
box.append(new Label("<b>Video</b>") { use_markup=true, xalign=0 });
|
||||
box.append(create_media_encryption_grid(video_encryption));
|
||||
}
|
||||
popover.set_child(box);
|
||||
|
@ -62,14 +62,14 @@ public class Dino.Ui.CallEncryptionButtonController {
|
|||
}
|
||||
|
||||
private Grid create_media_encryption_grid(Xmpp.Xep.Jingle.ContentEncryption? encryption) {
|
||||
Grid ret = new Grid() { row_spacing=3, column_spacing=5, visible=true };
|
||||
Grid ret = new Grid() { row_spacing=3, column_spacing=5 };
|
||||
if (encryption.peer_key.length > 0) {
|
||||
ret.attach(new Label("Peer call key") { xalign=0, visible=true }, 1, 2, 1, 1);
|
||||
ret.attach(new Label("<span font_family='monospace'>" + format_fingerprint(encryption.peer_key) + "</span>") { use_markup=true, max_width_chars=25, ellipsize=EllipsizeMode.MIDDLE, xalign=0, hexpand=true, visible=true }, 2, 2, 1, 1);
|
||||
ret.attach(new Label("Peer call key") { xalign=0 }, 1, 2, 1, 1);
|
||||
ret.attach(new Label("<span font_family='monospace'>" + format_fingerprint(encryption.peer_key) + "</span>") { use_markup=true, max_width_chars=25, ellipsize=EllipsizeMode.MIDDLE, xalign=0, hexpand=true }, 2, 2, 1, 1);
|
||||
}
|
||||
if (encryption.our_key.length > 0) {
|
||||
ret.attach(new Label("Your call key") { xalign=0, visible=true }, 1, 3, 1, 1);
|
||||
ret.attach(new Label("<span font_family='monospace'>" + format_fingerprint(encryption.our_key) + "</span>") { use_markup=true, max_width_chars=25, ellipsize=EllipsizeMode.MIDDLE, xalign=0, hexpand=true, visible=true }, 2, 3, 1, 1);
|
||||
ret.attach(new Label("Your call key") { xalign=0 }, 1, 3, 1, 1);
|
||||
ret.attach(new Label("<span font_family='monospace'>" + format_fingerprint(encryption.our_key) + "</span>") { use_markup=true, max_width_chars=25, ellipsize=EllipsizeMode.MIDDLE, xalign=0, hexpand=true }, 2, 3, 1, 1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -11,13 +11,13 @@ namespace Dino.Ui {
|
|||
|
||||
public CallWindowController controller;
|
||||
|
||||
public Overlay overlay = new Overlay() { visible=true };
|
||||
public Grid grid = new Grid() { visible=true };
|
||||
public CallBottomBar bottom_bar = new CallBottomBar() { visible=true };
|
||||
public Revealer bottom_bar_revealer = new Revealer() { valign=Align.END, transition_type=RevealerTransitionType.CROSSFADE, transition_duration=200, visible=true };
|
||||
public HeaderBar header_bar = new HeaderBar() { valign=Align.START, halign=Align.END, show_title_buttons=true, visible=true, opacity=0.0 };
|
||||
public Revealer header_bar_revealer = new Revealer() { halign=Align.END, valign=Align.START, transition_type=RevealerTransitionType.SLIDE_LEFT, transition_duration=200, visible=true, reveal_child=false };
|
||||
public Box own_video_box = new Box(Orientation.HORIZONTAL, 0) { halign=Align.END, valign=Align.END, visible=true };
|
||||
public Overlay overlay = new Overlay();
|
||||
public Grid grid = new Grid();
|
||||
public CallBottomBar bottom_bar = new CallBottomBar();
|
||||
public Revealer bottom_bar_revealer = new Revealer() { valign=Align.END, transition_type=RevealerTransitionType.CROSSFADE, transition_duration=200 };
|
||||
public HeaderBar header_bar = new HeaderBar() { valign=Align.START, halign=Align.END, show_title_buttons=true, opacity=0.0 };
|
||||
public Revealer header_bar_revealer = new Revealer() { halign=Align.END, valign=Align.START, transition_type=RevealerTransitionType.SLIDE_LEFT, transition_duration=200, reveal_child=false };
|
||||
public Box own_video_box = new Box(Orientation.HORIZONTAL, 0) { halign=Align.END, valign=Align.END };
|
||||
private Widget? own_video = null;
|
||||
private HashMap<string, ParticipantWidget> participant_widgets = new HashMap<string, ParticipantWidget>();
|
||||
private ArrayList<string> participants = new ArrayList<string>();
|
||||
|
@ -32,14 +32,14 @@ namespace Dino.Ui {
|
|||
public bool controls_active { get; set; default=true; }
|
||||
|
||||
construct {
|
||||
header_bar.get_style_context().add_class("call-header-bar");
|
||||
header_bar.add_css_class("call-header-bar");
|
||||
header_bar.title_widget = new Box(Orientation.VERTICAL, 0);
|
||||
// header_bar.spacing = 0;
|
||||
header_bar_revealer.set_child(header_bar);
|
||||
bottom_bar_revealer.set_child(bottom_bar);
|
||||
own_video_box.get_style_context().add_class("own-video");
|
||||
own_video_box.add_css_class("own-video");
|
||||
|
||||
this.get_style_context().add_class("dino-call-window");
|
||||
this.add_css_class("dino-call-window");
|
||||
|
||||
overlay.set_child(grid);
|
||||
overlay.add_overlay(own_video_box);
|
||||
|
@ -64,7 +64,7 @@ namespace Dino.Ui {
|
|||
this.notify["default-width"].connect(reposition_participant_widgets);
|
||||
this.notify["default-height"].connect(reposition_participant_widgets);
|
||||
|
||||
this.set_titlebar(new OutsideHeaderBar(this.header_bar) { visible=true });
|
||||
this.set_titlebar(new OutsideHeaderBar(this.header_bar));
|
||||
|
||||
reveal_control_elements();
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ namespace Dino.Ui {
|
|||
public void add_participant(string participant, ParticipantWidget participant_widget) {
|
||||
participant_widget.visible = true;
|
||||
this.bind_property("controls-active", participant_widget, "controls-active", BindingFlags.SYNC_CREATE);
|
||||
this.bind_property("controls-active", participant_widget.encryption_button, "controls-active", BindingFlags.SYNC_CREATE);
|
||||
this.bind_property("controls-active", participant_widget.encryption_button_controller, "controls-active", BindingFlags.SYNC_CREATE);
|
||||
|
||||
participants.add(participant);
|
||||
participant_widgets[participant] = participant_widget;
|
||||
|
@ -153,8 +153,9 @@ namespace Dino.Ui {
|
|||
|
||||
own_video = widget_;
|
||||
if (own_video == null) {
|
||||
own_video = new Box(Orientation.HORIZONTAL, 0) { hexpand=true, vexpand=true };
|
||||
own_video = new Box(Orientation.HORIZONTAL, 0);
|
||||
}
|
||||
own_video.hexpand = own_video.vexpand = true;
|
||||
own_video.visible = true;
|
||||
own_video_box.append(own_video);
|
||||
}
|
||||
|
|
|
@ -134,10 +134,11 @@ public class Dino.Ui.CallWindowController : Object {
|
|||
warning("suspend inhibit request failed or unsupported");
|
||||
}
|
||||
|
||||
call_window.destroy.connect(() => {
|
||||
call_window.close_request.connect(() => {
|
||||
if (inhibit_cookie != 0) {
|
||||
app.uninhibit(inhibit_cookie);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -235,7 +236,7 @@ public class Dino.Ui.CallWindowController : Object {
|
|||
ParticipantWidget participant_widget = new ParticipantWidget(participant_name);
|
||||
participant_widget.may_show_invite_button = !participant_widgets.is_empty;
|
||||
participant_widget.debug_information_clicked.connect(() => {
|
||||
var conn_details_window = new CallConnectionDetailsWindow() { title=participant_name, visible=true };
|
||||
var conn_details_window = new CallConnectionDetailsWindow() { title=participant_name };
|
||||
conn_details_window.update_content(peer_states[participant_id].get_info());
|
||||
uint timeout_handle_id = Timeout.add_seconds(1, () => {
|
||||
conn_details_window.update_content(peer_states[participant_id].get_info());
|
||||
|
@ -361,7 +362,9 @@ public class Dino.Ui.CallWindowController : Object {
|
|||
public override void dispose() {
|
||||
foreach (ulong handler_id in call_window_handler_ids) call_window.disconnect(handler_id);
|
||||
foreach (ulong handler_id in bottom_bar_handler_ids) call_window.bottom_bar.disconnect(handler_id);
|
||||
participant_widgets.keys.@foreach((peer_id) => { remove_participant(peer_id); return true; });
|
||||
foreach (string peer_id in participant_widgets.keys) {
|
||||
remove_participant(peer_id);
|
||||
}
|
||||
|
||||
call_window_handler_ids = bottom_bar_handler_ids = new ulong[0];
|
||||
own_video.detach();
|
||||
|
|
|
@ -10,15 +10,15 @@ namespace Dino.Ui {
|
|||
|
||||
public Overlay overlay = new Overlay();
|
||||
public Widget main_widget;
|
||||
public HeaderBar header_bar = new HeaderBar() { valign=Align.START, visible=true };
|
||||
public HeaderBar header_bar = new HeaderBar() { valign=Align.START };
|
||||
public Label title_label = new Label("");
|
||||
public Label subtitle_label = new Label("");
|
||||
public Box inner_box = new Box(Orientation.HORIZONTAL, 0) { margin_start=5, margin_top=5, hexpand=true, visible=true };
|
||||
public Box title_box = new Box(Orientation.VERTICAL, 0) { valign=Align.CENTER, hexpand=true, visible=true };
|
||||
public MenuButton encryption_button = new MenuButton() { opacity=0, has_frame=false, height_request=30, width_request=30, margin_end=5, visible=true };
|
||||
public Box inner_box = new Box(Orientation.HORIZONTAL, 0) { margin_start=5, margin_top=5, hexpand=true };
|
||||
public Box title_box = new Box(Orientation.VERTICAL, 0) { valign=Align.CENTER, hexpand=true };
|
||||
public MenuButton encryption_button = new MenuButton() { opacity=0, has_frame=false, height_request=30, width_request=30, margin_end=5 };
|
||||
public CallEncryptionButtonController encryption_button_controller;
|
||||
public MenuButton menu_button = new MenuButton() { icon_name="open-menu-symbolic", has_frame=false, visible=true };
|
||||
public Button invite_button = new Button.from_icon_name("dino-account-plus") { has_frame=false, visible=true };
|
||||
public MenuButton menu_button = new MenuButton() { icon_name="open-menu-symbolic", has_frame=false };
|
||||
public Button invite_button = new Button.from_icon_name("dino-account-plus") { has_frame=false };
|
||||
public bool shows_video = false;
|
||||
public string? participant_name;
|
||||
|
||||
|
@ -40,18 +40,19 @@ namespace Dino.Ui {
|
|||
this.participant_name = participant_name;
|
||||
|
||||
Box titles_box = new Box(Orientation.VERTICAL, 0) { valign=Align.CENTER };
|
||||
titles_box.add_css_class("titles");
|
||||
title_label.attributes = new AttrList();
|
||||
title_label.attributes.insert(Pango.attr_weight_new(Weight.BOLD));
|
||||
titles_box.append(title_label);
|
||||
subtitle_label.attributes = new AttrList();
|
||||
subtitle_label.attributes.insert(Pango.attr_scale_new(Pango.Scale.SMALL));
|
||||
subtitle_label.get_style_context().add_class("dim-label");
|
||||
subtitle_label.add_css_class("dim-label");
|
||||
titles_box.append(subtitle_label);
|
||||
|
||||
header_bar.set_title_widget(titles_box);
|
||||
title_label.label = participant_name;
|
||||
|
||||
header_bar.get_style_context().add_class("participant-header-bar");
|
||||
header_bar.add_css_class("participant-header-bar");
|
||||
header_bar.pack_start(invite_button);
|
||||
header_bar.pack_start(encryption_button);
|
||||
header_bar.pack_end(menu_button);
|
||||
|
@ -73,14 +74,14 @@ namespace Dino.Ui {
|
|||
|
||||
header_bar.show_title_buttons = is_highest_row;
|
||||
if (is_highest_row) {
|
||||
header_bar.get_style_context().add_class("call-header-background");
|
||||
header_bar.add_css_class("call-header-background");
|
||||
Gtk.Settings? gtk_settings = Gtk.Settings.get_default();
|
||||
if (gtk_settings != null) {
|
||||
string[] buttons = gtk_settings.gtk_decoration_layout.split(":");
|
||||
header_bar.decoration_layout = (is_start ? buttons[0] : "") + ":" + (is_end && buttons.length == 2 ? buttons[1] : "");
|
||||
}
|
||||
} else {
|
||||
header_bar.get_style_context().remove_class("call-header-background");
|
||||
header_bar.remove_css_class("call-header-background");
|
||||
}
|
||||
reveal_or_hide_controls();
|
||||
}
|
||||
|
@ -93,9 +94,9 @@ namespace Dino.Ui {
|
|||
|
||||
public void set_placeholder(Conversation? conversation, StreamInteractor stream_interactor) {
|
||||
shows_video = false;
|
||||
Box box = new Box(Orientation.HORIZONTAL, 0) { visible=true };
|
||||
box.get_style_context().add_class("video-placeholder-box");
|
||||
AvatarImage avatar = new AvatarImage() { allow_gray=false, hexpand=true, vexpand=true, halign=Align.CENTER, valign=Align.CENTER, height=100, width=100, visible=true };
|
||||
Box box = new Box(Orientation.HORIZONTAL, 0);
|
||||
box.add_css_class("video-placeholder-box");
|
||||
AvatarImage avatar = new AvatarImage() { allow_gray=false, hexpand=true, vexpand=true, halign=Align.CENTER, valign=Align.CENTER, height=100, width=100 };
|
||||
if (conversation != null) {
|
||||
avatar.set_conversation(stream_interactor, conversation);
|
||||
} else {
|
||||
|
@ -133,6 +134,10 @@ namespace Dino.Ui {
|
|||
}
|
||||
}
|
||||
|
||||
public bool is_menu_active() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void reveal_or_hide_controls() {
|
||||
header_bar.opacity = controls_active ? 1.0 : 0.0;
|
||||
invite_button.visible = may_show_invite_button && is_highest_row && is_start_row;
|
||||
|
|
|
@ -11,7 +11,7 @@ public class Dino.Ui.VideoSettingsPopover : Gtk.Popover {
|
|||
private HashMap<ListBoxRow, Plugins.MediaDevice> row_device = new HashMap<ListBoxRow, Plugins.MediaDevice>();
|
||||
|
||||
public VideoSettingsPopover() {
|
||||
Box box = new Box(Orientation.VERTICAL, 15) { visible=true };
|
||||
Box box = new Box(Orientation.VERTICAL, 15);
|
||||
box.append(create_camera_box());
|
||||
|
||||
this.set_child(box);
|
||||
|
@ -21,19 +21,19 @@ public class Dino.Ui.VideoSettingsPopover : Gtk.Popover {
|
|||
Plugins.VideoCallPlugin call_plugin = Dino.Application.get_default().plugin_registry.video_call_plugin;
|
||||
Gee.List<Plugins.MediaDevice> devices = call_plugin.get_devices("video", false);
|
||||
|
||||
Box camera_box = new Box(Orientation.VERTICAL, 10) { visible=true };
|
||||
camera_box.append(new Label("<b>" + _("Cameras") + "</b>") { use_markup=true, xalign=0, visible=true, can_focus=true /* grab initial focus*/ });
|
||||
Box camera_box = new Box(Orientation.VERTICAL, 10);
|
||||
camera_box.append(new Label("<b>" + _("Cameras") + "</b>") { use_markup=true, xalign=0, can_focus=true /* grab initial focus*/ });
|
||||
|
||||
if (devices.size == 0) {
|
||||
camera_box.append(new Label(_("No camera found.")) { visible=true });
|
||||
camera_box.append(new Label(_("No camera found.")));
|
||||
} else {
|
||||
ListBox list_box = new ListBox() { activate_on_single_click=true, selection_mode=SelectionMode.SINGLE, visible=true };
|
||||
ListBox list_box = new ListBox() { activate_on_single_click=true, selection_mode=SelectionMode.SINGLE };
|
||||
list_box.set_header_func(listbox_header_func);
|
||||
Frame frame = new Frame(null) { visible=true };
|
||||
Frame frame = new Frame(null);
|
||||
frame.set_child(list_box);
|
||||
foreach (Plugins.MediaDevice device in devices) {
|
||||
Label display_name_label = new Label(device.display_name) { xalign=0, visible=true };
|
||||
Image image = new Image.from_icon_name("object-select-symbolic") { visible=true };
|
||||
Label display_name_label = new Label(device.display_name) { xalign=0 };
|
||||
Image image = new Image.from_icon_name("object-select-symbolic");
|
||||
if (current_device == null || current_device.id != device.id) {
|
||||
image.opacity = 0;
|
||||
}
|
||||
|
@ -44,19 +44,19 @@ public class Dino.Ui.VideoSettingsPopover : Gtk.Popover {
|
|||
image.opacity = 1;
|
||||
}
|
||||
});
|
||||
Box device_box = new Box(Orientation.HORIZONTAL, 0) { spacing=7, visible=true };
|
||||
Box device_box = new Box(Orientation.HORIZONTAL, 0) { spacing=7 };
|
||||
device_box.append(image);
|
||||
Box label_box = new Box(Orientation.VERTICAL, 0) { visible = true };
|
||||
label_box.append(display_name_label);
|
||||
if (device.detail_name != null) {
|
||||
Label detail_name_label = new Label(device.detail_name) { xalign=0, visible=true };
|
||||
detail_name_label.get_style_context().add_class("dim-label");
|
||||
Label detail_name_label = new Label(device.detail_name) { xalign=0 };
|
||||
detail_name_label.add_css_class("dim-label");
|
||||
detail_name_label.attributes = new Pango.AttrList();
|
||||
detail_name_label.attributes.insert(Pango.attr_scale_new(0.8));
|
||||
label_box.append(detail_name_label);
|
||||
}
|
||||
device_box.append(label_box);
|
||||
ListBoxRow list_box_row = new ListBoxRow() { visible=true };
|
||||
ListBoxRow list_box_row = new ListBoxRow();
|
||||
list_box_row.set_child(device_box);
|
||||
list_box.append(list_box_row);
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ public class ChatTextViewController : Object {
|
|||
|
||||
public void initialize_for_conversation(Conversation conversation) {
|
||||
occupants_tab_completor.initialize_for_conversation(conversation);
|
||||
widget.initialize_for_conversation(conversation);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,40 +38,31 @@ public class ChatTextView : Box {
|
|||
public TextView text_view = new TextView() { hexpand=true, wrap_mode=Gtk.WrapMode.WORD_CHAR, valign=Align.CENTER, margin_top=7, margin_bottom=7 };
|
||||
private int vscrollbar_min_height;
|
||||
private SmileyConverter smiley_converter;
|
||||
// private SpellChecker spell_checker;
|
||||
|
||||
construct {
|
||||
scrolled_window.set_child(text_view);
|
||||
this.append(scrolled_window);
|
||||
|
||||
smiley_converter = new SmileyConverter(text_view);
|
||||
|
||||
// scrolled_window.get_vscrollbar().get_preferred_size(out vscrollbar_min_size, null);
|
||||
scrolled_window.vadjustment.notify["upper"].connect(on_upper_notify);
|
||||
|
||||
var text_input_key_events = new EventControllerKey();
|
||||
text_input_key_events.key_pressed.connect(on_text_input_key_press);
|
||||
text_view.add_controller(text_input_key_events);
|
||||
|
||||
smiley_converter = new SmileyConverter(text_view);
|
||||
|
||||
scrolled_window.vadjustment.changed.connect(on_upper_notify);
|
||||
|
||||
text_view.realize.connect(() => {
|
||||
var minimum_size = new Requisition();
|
||||
scrolled_window.get_preferred_size(out minimum_size, null);
|
||||
vscrollbar_min_height = minimum_size.height;
|
||||
});
|
||||
// Gtk.drag_dest_unset(text_view);
|
||||
}
|
||||
|
||||
public void initialize_for_conversation(Conversation conversation) {
|
||||
// spell_checker.initialize_for_conversation(conversation);
|
||||
}
|
||||
|
||||
// public override void get_preferred_size(out Gtk.Requisition minimum_size, out Gtk.Requisition natural_size) {
|
||||
// base.get_preferred_height(out min_height, out nat_height);
|
||||
// min_height = nat_height;
|
||||
// }
|
||||
|
||||
private void on_upper_notify() {
|
||||
scrolled_window.vadjustment.value = scrolled_window.vadjustment.upper - scrolled_window.vadjustment.page_size;
|
||||
// hack. otherwise the textview would only show the last row(s) when entering a new row on some systems.
|
||||
if (text_view.get_height() < scrolled_window.max_content_height - 20) {
|
||||
scrolled_window.vadjustment.page_size = scrolled_window.vadjustment.upper;
|
||||
}
|
||||
|
||||
// hack for vscrollbar not requiring space and making textview higher //TODO doesn't resize immediately
|
||||
scrolled_window.get_vscrollbar().visible = (scrolled_window.vadjustment.upper > scrolled_window.max_content_height - 2 * this.vscrollbar_min_height);
|
||||
|
|
|
@ -15,16 +15,39 @@ public class EncryptionButton {
|
|||
private Map<CheckButton, Plugins.EncryptionListEntry> encryption_radios = new HashMap<CheckButton, Plugins.EncryptionListEntry>();
|
||||
private string? current_icon;
|
||||
private StreamInteractor stream_interactor;
|
||||
private SimpleAction action;
|
||||
|
||||
public EncryptionButton(StreamInteractor stream_interactor, MenuButton menu_button) {
|
||||
this.stream_interactor = stream_interactor;
|
||||
this.menu_button = menu_button;
|
||||
|
||||
Builder builder = new Builder.from_resource("/im/dino/Dino/menu_encryption.ui");
|
||||
menu_button.popover = builder.get_object("menu_encryption") as PopoverMenu;
|
||||
Box encryption_box = builder.get_object("encryption_box") as Box;
|
||||
button_unencrypted = builder.get_object("button_unencrypted") as CheckButton;
|
||||
button_unencrypted.toggled.connect(encryption_button_toggled);
|
||||
// Build menu model including "Unencrypted" and all registered encryption entries
|
||||
Menu menu_model = new Menu();
|
||||
|
||||
MenuItem unencrypted_item = new MenuItem(_("Unencrypted"), "enc.encryption");
|
||||
unencrypted_item.set_action_and_target_value("enc.encryption", new Variant.int32(Encryption.NONE));
|
||||
menu_model.append_item(unencrypted_item);
|
||||
|
||||
Application app = GLib.Application.get_default() as Application;
|
||||
foreach (var e in app.plugin_registry.encryption_list_entries) {
|
||||
MenuItem item = new MenuItem(e.name, "enc.encryption");
|
||||
item.set_action_and_target_value("enc.encryption", new Variant.int32(e.encryption));
|
||||
menu_model.append_item(item);
|
||||
}
|
||||
|
||||
// Create action to act on menu selections (stateful => radio buttons)
|
||||
SimpleActionGroup action_group = new SimpleActionGroup();
|
||||
action = new SimpleAction.stateful("encryption", VariantType.INT32, new Variant.int32(Encryption.NONE));
|
||||
action.activate.connect((parameter) => {
|
||||
action.set_state(parameter);
|
||||
this.conversation.encryption = (Encryption) parameter.get_int32();
|
||||
});
|
||||
action_group.insert(action);
|
||||
menu_button.insert_action_group("enc", action_group);
|
||||
|
||||
// Create and set popover menu
|
||||
Gtk.PopoverMenu popover_menu = new Gtk.PopoverMenu.from_model(menu_model);
|
||||
menu_button.popover = popover_menu;
|
||||
|
||||
stream_interactor.get_module(MucManager.IDENTITY).room_info_updated.connect((account, muc_jid) => {
|
||||
if (conversation != null && conversation.account.equals(account) && conversation.counterpart.equals(muc_jid)) {
|
||||
|
@ -32,15 +55,6 @@ public class EncryptionButton {
|
|||
}
|
||||
});
|
||||
|
||||
Application app = GLib.Application.get_default() as Application;
|
||||
foreach (var e in app.plugin_registry.encryption_list_entries) {
|
||||
CheckButton btn = new CheckButton.with_label(e.name);
|
||||
btn.set_group(button_unencrypted);
|
||||
encryption_radios[btn] = e;
|
||||
btn.toggled.connect(encryption_button_toggled);
|
||||
btn.visible = true;
|
||||
encryption_box.prepend(btn);
|
||||
}
|
||||
menu_button.activate.connect(update_encryption_menu_state);
|
||||
}
|
||||
|
||||
|
@ -61,16 +75,8 @@ public class EncryptionButton {
|
|||
}
|
||||
|
||||
private void update_encryption_menu_state() {
|
||||
foreach (CheckButton e in encryption_radios.keys) {
|
||||
if (conversation.encryption == encryption_radios[e].encryption) {
|
||||
e.set_active(true);
|
||||
encryption_changed(encryption_radios[e]);
|
||||
}
|
||||
}
|
||||
if (conversation.encryption == Encryption.NONE) {
|
||||
button_unencrypted.set_active(true);
|
||||
encryption_changed(null);
|
||||
}
|
||||
action.set_state(new Variant.int32(conversation.encryption));
|
||||
action.change_state(new Variant.int32(conversation.encryption));
|
||||
}
|
||||
|
||||
private void set_icon(string icon) {
|
||||
|
|
|
@ -66,28 +66,28 @@ public class View : Box {
|
|||
public void set_input_state(Plugins.InputFieldStatus.MessageType message_type) {
|
||||
switch (message_type) {
|
||||
case Plugins.InputFieldStatus.MessageType.NONE:
|
||||
this.get_style_context().remove_class("dino-input-warning");
|
||||
this.get_style_context().remove_class("dino-input-error");
|
||||
this.remove_css_class("dino-input-warning");
|
||||
this.remove_css_class("dino-input-error");
|
||||
break;
|
||||
case Plugins.InputFieldStatus.MessageType.INFO:
|
||||
this.get_style_context().remove_class("dino-input-warning");
|
||||
this.get_style_context().remove_class("dino-input-error");
|
||||
this.remove_css_class("dino-input-warning");
|
||||
this.remove_css_class("dino-input-error");
|
||||
break;
|
||||
case Plugins.InputFieldStatus.MessageType.WARNING:
|
||||
this.get_style_context().add_class("dino-input-warning");
|
||||
this.get_style_context().remove_class("dino-input-error");
|
||||
this.add_css_class("dino-input-warning");
|
||||
this.remove_css_class("dino-input-error");
|
||||
break;
|
||||
case Plugins.InputFieldStatus.MessageType.ERROR:
|
||||
this.get_style_context().remove_class("dino-input-warning");
|
||||
this.get_style_context().add_class("dino-input-error");
|
||||
this.remove_css_class("dino-input-warning");
|
||||
this.add_css_class("dino-input-error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void highlight_state_description() {
|
||||
chat_input_status.get_style_context().add_class("input-status-highlight-once");
|
||||
chat_input_status.add_css_class("input-status-highlight-once");
|
||||
Timeout.add_seconds(1, () => {
|
||||
chat_input_status.get_style_context().remove_class("input-status-highlight-once");
|
||||
chat_input_status.remove_css_class("input-status-highlight-once");
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ public class BlockingProvider : Plugins.ContactDetailsProvider, Object {
|
|||
|
||||
if (stream_interactor.get_module(BlockingManager.IDENTITY).is_supported(conversation.account)) {
|
||||
bool is_blocked = stream_interactor.get_module(BlockingManager.IDENTITY).is_blocked(conversation.account, conversation.counterpart);
|
||||
Switch sw = new Switch() { active=is_blocked, valign=Align.CENTER, visible=true };
|
||||
Switch sw = new Switch() { active=is_blocked, valign=Align.CENTER };
|
||||
sw.state_set.connect((state) => {
|
||||
if (state) {
|
||||
stream_interactor.get_module(BlockingManager.IDENTITY).block(conversation.account, conversation.counterpart);
|
||||
|
|
|
@ -37,7 +37,18 @@ public class Dialog : Gtk.Dialog {
|
|||
title = conversation.type_ == Conversation.Type.GROUPCHAT ? _("Conference Details") : _("Contact Details");
|
||||
if (Util.use_csd()) {
|
||||
// TODO get_header_bar directly returns a HeaderBar in vala > 0.48
|
||||
// ((HeaderBar) get_header_bar()).set_subtitle(Util.get_conversation_display_name(stream_interactor, conversation));
|
||||
Box titles_box = new Box(Orientation.VERTICAL, 0) { valign=Align.CENTER };
|
||||
var title_label = new Label(title);
|
||||
title_label.attributes = new AttrList();
|
||||
title_label.attributes.insert(Pango.attr_weight_new(Weight.BOLD));
|
||||
titles_box.append(title_label);
|
||||
var subtitle_label = new Label(Util.get_conversation_display_name(stream_interactor, conversation));
|
||||
subtitle_label.attributes = new AttrList();
|
||||
subtitle_label.attributes.insert(Pango.attr_scale_new(Pango.Scale.SMALL));
|
||||
subtitle_label.add_css_class("dim-label");
|
||||
titles_box.append(subtitle_label);
|
||||
|
||||
get_header_bar().set_title_widget(titles_box);
|
||||
}
|
||||
setup_top();
|
||||
|
||||
|
@ -53,9 +64,10 @@ public class Dialog : Gtk.Dialog {
|
|||
provider.populate(conversation, contact_details, Plugins.WidgetType.GTK4);
|
||||
}
|
||||
|
||||
// destroy.connect(() => {
|
||||
// contact_details.save();
|
||||
// });
|
||||
close_request.connect(() => {
|
||||
contact_details.save();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
private void setup_top() {
|
||||
|
@ -83,16 +95,16 @@ public class Dialog : Gtk.Dialog {
|
|||
Widget w = (Widget) wo;
|
||||
add_category(category);
|
||||
|
||||
ListBoxRow list_row = new ListBoxRow() { activatable=false, visible=true };
|
||||
Box row = new Box(Orientation.HORIZONTAL, 20) { margin_start=15, margin_end=15, margin_top=3, margin_bottom=3, visible=true };
|
||||
ListBoxRow list_row = new ListBoxRow() { activatable=false };
|
||||
Box row = new Box(Orientation.HORIZONTAL, 20) { margin_start=15, margin_end=15, margin_top=3, margin_bottom=3 };
|
||||
list_row.set_child(row);
|
||||
Label label_label = new Label(label) { xalign=0, yalign=0.5f, hexpand=true, visible=true };
|
||||
Label label_label = new Label(label) { xalign=0, yalign=0.5f, hexpand=true };
|
||||
if (description != null && description != "") {
|
||||
Box box = new Box(Orientation.VERTICAL, 0) { visible=true };
|
||||
Box box = new Box(Orientation.VERTICAL, 0);
|
||||
box.append(label_label);
|
||||
Label desc_label = new Label("") { xalign=0, yalign=0.5f, hexpand=true, visible=true };
|
||||
Label desc_label = new Label("") { xalign=0, yalign=0.5f, hexpand=true };
|
||||
desc_label.set_markup("<span size='small'>%s</span>".printf(Markup.escape_text(description)));
|
||||
desc_label.get_style_context().add_class("dim-label");
|
||||
desc_label.add_css_class("dim-label");
|
||||
box.append(desc_label);
|
||||
row.append(box);
|
||||
} else {
|
||||
|
@ -101,11 +113,11 @@ public class Dialog : Gtk.Dialog {
|
|||
|
||||
Widget widget = w;
|
||||
if (widget.get_type().is_a(typeof(Entry))) {
|
||||
Util.EntryLabelHybrid hybrid = new Util.EntryLabelHybrid.wrap(widget as Entry) { xalign=1, visible=true };
|
||||
Util.EntryLabelHybrid hybrid = new Util.EntryLabelHybrid.wrap(widget as Entry) { xalign=1 };
|
||||
hybrid_group.add(hybrid);
|
||||
widget = hybrid;
|
||||
} else if (widget.get_type().is_a(typeof(ComboBoxText))) {
|
||||
Util.ComboBoxTextLabelHybrid hybrid = new Util.ComboBoxTextLabelHybrid.wrap(widget as ComboBoxText) { xalign=1, visible=true };
|
||||
Util.ComboBoxTextLabelHybrid hybrid = new Util.ComboBoxTextLabelHybrid.wrap(widget as ComboBoxText) { xalign=1 };
|
||||
hybrid_group.add(hybrid);
|
||||
widget = hybrid;
|
||||
}
|
||||
|
@ -116,26 +128,26 @@ public class Dialog : Gtk.Dialog {
|
|||
row.append(widget);
|
||||
categories[category].append(list_row);
|
||||
|
||||
int width = get_content_area().get_width();
|
||||
int pref_height, pref_width;
|
||||
// get_content_area().get_preferred_height(null, out pref_height);
|
||||
// get_preferred_width(out pref_width, null);
|
||||
// resize(pref_width, int.min(500, pref_height));
|
||||
get_content_area().measure(Orientation.VERTICAL, width, null, out pref_height, null, null);
|
||||
default_height = pref_height;
|
||||
}
|
||||
|
||||
private void add_category(string category) {
|
||||
if (!categories.has_key(category)) {
|
||||
ListBox list_box = new ListBox() { selection_mode=SelectionMode.NONE, visible=true };
|
||||
ListBox list_box = new ListBox() { selection_mode=SelectionMode.NONE };
|
||||
categories[category] = list_box;
|
||||
list_box.set_header_func((row, before_row) => {
|
||||
if (row.get_header() == null && before_row != null) {
|
||||
row.set_header(new Separator(Orientation.HORIZONTAL));
|
||||
}
|
||||
});
|
||||
Box box = new Box(Orientation.VERTICAL, 5) { margin_top=12, margin_bottom=12, visible=true };
|
||||
Label category_label = new Label("") { xalign=0, visible=true };
|
||||
Box box = new Box(Orientation.VERTICAL, 5) { margin_top=12, margin_bottom=12 };
|
||||
Label category_label = new Label("") { xalign=0 };
|
||||
category_label.set_markup(@"<b>$(Markup.escape_text(category))</b>");
|
||||
box.append(category_label);
|
||||
Frame frame = new Frame(null) { visible=true };
|
||||
Frame frame = new Frame(null);
|
||||
frame.set_child(list_box);
|
||||
box.append(frame);
|
||||
main_box.append(box);
|
||||
|
|
|
@ -20,7 +20,7 @@ public class PermissionsProvider : Plugins.ContactDetailsProvider, Object {
|
|||
if (own_jid == null) return;
|
||||
|
||||
if (stream_interactor.get_module(MucManager.IDENTITY).get_role(own_jid, conversation.account) == Xmpp.Xep.Muc.Role.VISITOR){
|
||||
Button voice_request = new Button.with_label(_("Request")) { visible=true };
|
||||
Button voice_request = new Button.with_label(_("Request"));
|
||||
voice_request.clicked.connect(()=>stream_interactor.get_module(MucManager.IDENTITY).request_voice(conversation.account, conversation.counterpart));
|
||||
contact_details.add(_("Permissions"), _("Request permission to send messages"), "", voice_request);
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ public class SettingsProvider : Plugins.ContactDetailsProvider, Object {
|
|||
combobox_notifications.active_id = get_notify_setting_id(conversation.notify_setting);
|
||||
combobox_notifications.changed.connect(() => { conversation.notify_setting = get_notify_setting(combobox_notifications.active_id); } );
|
||||
} else if (conversation.type_ == Conversation.Type.GROUPCHAT) {
|
||||
ComboBoxText combobox = new ComboBoxText() { visible=true };
|
||||
ComboBoxText combobox = new ComboBoxText();
|
||||
combobox.append("default", get_notify_setting_string(Conversation.NotifySetting.DEFAULT, conversation.get_notification_default_setting(stream_interactor)));
|
||||
combobox.append("highlight", get_notify_setting_string(Conversation.NotifySetting.HIGHLIGHT));
|
||||
combobox.append("on", get_notify_setting_string(Conversation.NotifySetting.ON));
|
||||
|
@ -119,7 +119,7 @@ public class SettingsProvider : Plugins.ContactDetailsProvider, Object {
|
|||
|
||||
private ComboBoxText get_combobox(bool default_val) {
|
||||
ComboBoxText combobox = new ComboBoxText();
|
||||
combobox = new ComboBoxText() { visible=true };
|
||||
combobox = new ComboBoxText();
|
||||
string default_setting = default_val ? _("On") : _("Off");
|
||||
combobox.append("default", _("Default: %s").printf(default_setting) );
|
||||
combobox.append("on", _("On"));
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
using Gtk;
|
||||
|
||||
namespace Dino.Ui {
|
||||
|
||||
public static ListItemFactory get_item_factory() {
|
||||
SignalListItemFactory item_factory = new SignalListItemFactory();
|
||||
item_factory.setup.connect((list_item) => { on_setup(list_item); });
|
||||
item_factory.bind.connect((list_item) => { on_bind(list_item); });
|
||||
return item_factory;
|
||||
}
|
||||
|
||||
public static void on_setup(ListItem listitem) {
|
||||
listitem.child = new ConversationItemWidget();
|
||||
}
|
||||
|
||||
public static void on_bind(ListItem listitem) {
|
||||
MessageViewModel view_model = (MessageViewModel) listitem.get_item();
|
||||
ConversationItemWidget view = (ConversationItemWidget) listitem.get_child();
|
||||
|
||||
view_model.bind_property("name", view.name_label, "label", BindingFlags.SYNC_CREATE);
|
||||
view_model.bind_property("time", view.time_label, "label", BindingFlags.SYNC_CREATE);
|
||||
|
||||
Label? label = view.content_widget as Label;
|
||||
if (label == null) {
|
||||
label = new Label("") { use_markup=true, xalign=0, selectable=true, wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR, hexpand=true, vexpand=true };
|
||||
view.set_content_widget(label);
|
||||
}
|
||||
view_model.bind_property("message", label, "label", BindingFlags.SYNC_CREATE);
|
||||
|
||||
view_model.bind_property("encryption-icon-name", view.encrypted_image, "icon-name", BindingFlags.SYNC_CREATE);
|
||||
view_model.bind_property("encryption-icon-tooltip", view.encrypted_image, "tooltip-text", BindingFlags.SYNC_CREATE);
|
||||
|
||||
view_model.bind_property("marked-icon-name", view.marked_image, "icon-name", BindingFlags.SYNC_CREATE);
|
||||
view_model.bind_property("marked-icon-tooltip", view.marked_image, "tooltip-text", BindingFlags.SYNC_CREATE);
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ namespace Dino.Ui {
|
|||
public override Object? get_widget(Plugins.ConversationItemWidgetInterface outer, Plugins.WidgetType type) {
|
||||
CallItem call_item = content_item as CallItem;
|
||||
CallState? call_state = stream_interactor.get_module(Calls.IDENTITY).call_states[call_item.call];
|
||||
return new CallWidget(stream_interactor, call_item.call, call_state, call_item.conversation) { visible=true };
|
||||
return new CallWidget(stream_interactor, call_item.call, call_state, call_item.conversation);
|
||||
}
|
||||
|
||||
public override Gee.List<Plugins.MessageAction>? get_item_actions(Plugins.WidgetType type) { return null; }
|
||||
|
@ -94,17 +94,17 @@ namespace Dino.Ui {
|
|||
}
|
||||
|
||||
foreach (Jid counterpart in call.counterparts) {
|
||||
AvatarImage image = new AvatarImage() { force_gray=true, margin_top=2, visible=true };
|
||||
AvatarImage image = new AvatarImage() { force_gray=true, margin_top=2 };
|
||||
image.set_conversation_participant(stream_interactor, conversation, counterpart.bare_jid);
|
||||
multiparty_peer_box.append(image);
|
||||
multiparty_peer_widgets.add(image);
|
||||
}
|
||||
AvatarImage image2 = new AvatarImage() { force_gray=true, margin_top=2, visible=true };
|
||||
AvatarImage image2 = new AvatarImage() { force_gray=true, margin_top=2 };
|
||||
image2.set_conversation_participant(stream_interactor, conversation, call.account.bare_jid);
|
||||
multiparty_peer_box.append(image2);
|
||||
multiparty_peer_widgets.add(image2);
|
||||
|
||||
outer_additional_box.get_style_context().add_class("multiparty-participants");
|
||||
outer_additional_box.add_css_class("multiparty-participants");
|
||||
|
||||
multiparty_peer_box.visible = true;
|
||||
incoming_call_box.visible = false;
|
||||
|
@ -113,8 +113,8 @@ namespace Dino.Ui {
|
|||
|
||||
private void update_call_state() {
|
||||
incoming_call_revealer.reveal_child = false;
|
||||
incoming_call_revealer.get_style_context().remove_class("incoming");
|
||||
outer_additional_box.get_style_context().remove_class("incoming-call-box");
|
||||
incoming_call_revealer.remove_css_class("incoming");
|
||||
outer_additional_box.remove_css_class("incoming-call-box");
|
||||
|
||||
// It doesn't make sense to display MUC calls as missed or declined by the whole MUC. Just display as ended.
|
||||
// TODO: maybe not let them be missed/declined in first place.
|
||||
|
@ -139,8 +139,8 @@ namespace Dino.Ui {
|
|||
subtitle_label.label = "Ring ring…!";
|
||||
incoming_call_box.visible = true;
|
||||
incoming_call_revealer.reveal_child = true;
|
||||
incoming_call_revealer.get_style_context().add_class("incoming");
|
||||
outer_additional_box.get_style_context().add_class("incoming-call-box");
|
||||
incoming_call_revealer.add_css_class("incoming");
|
||||
outer_additional_box.add_css_class("incoming-call-box");
|
||||
} else {
|
||||
subtitle_label.label = "Dependencies for call support not met";
|
||||
}
|
||||
|
|
|
@ -77,11 +77,11 @@ private class MetaChatStateItem : Plugins.MetaConversationItem {
|
|||
}
|
||||
|
||||
public override Object? get_widget(Plugins.ConversationItemWidgetInterface outer, Plugins.WidgetType widget_type) {
|
||||
label = new Label("") { xalign=0, vexpand=true, visible=true };
|
||||
label.get_style_context().add_class("dim-label");
|
||||
image = new AvatarImage() { margin_top=2, valign=Align.START, visible=true };
|
||||
label = new Label("") { xalign=0, vexpand=true };
|
||||
label.add_css_class("dim-label");
|
||||
image = new AvatarImage() { margin_top=2, valign=Align.START };
|
||||
|
||||
Box image_content_box = new Box(Orientation.HORIZONTAL, 8) { visible=true };
|
||||
Box image_content_box = new Box(Orientation.HORIZONTAL, 8);
|
||||
image_content_box.append(image);
|
||||
image_content_box.append(label);
|
||||
|
||||
|
|
|
@ -18,7 +18,12 @@ public class ConversationItemSkeleton : Plugins.ConversationItemWidgetInterface,
|
|||
|
||||
public Widget? content_widget = null;
|
||||
|
||||
public bool show_skeleton { get; set; default=false; }
|
||||
private bool show_skeleton_ = false;
|
||||
public bool show_skeleton {
|
||||
get { return show_skeleton_; }
|
||||
set {
|
||||
show_skeleton_ = value && content_meta_item != null && content_meta_item.requires_header && content_meta_item.requires_avatar; }
|
||||
}
|
||||
public bool last_group_item { get; set; default=true; }
|
||||
|
||||
public StreamInteractor stream_interactor;
|
||||
|
@ -26,7 +31,7 @@ public class ConversationItemSkeleton : Plugins.ConversationItemWidgetInterface,
|
|||
public Plugins.MetaConversationItem item;
|
||||
public bool item_in_edit_mode { get; set; }
|
||||
public Entities.Message.Marked item_mark { get; set; }
|
||||
public ContentMetaItem? content_meta_item = null;
|
||||
public ContentMetaItem content_meta_item = null;
|
||||
public Widget? widget = null;
|
||||
|
||||
private uint time_update_timeout = 0;
|
||||
|
@ -40,7 +45,7 @@ public class ConversationItemSkeleton : Plugins.ConversationItemWidgetInterface,
|
|||
|
||||
Builder builder = new Builder.from_resource("/im/dino/Dino/conversation_item_widget.ui");
|
||||
main_grid = (Grid) builder.get_object("main_grid");
|
||||
main_grid.get_style_context().add_class("message-box");
|
||||
main_grid.add_css_class("message-box");
|
||||
name_label = (Label) builder.get_object("name_label");
|
||||
time_label = (Label) builder.get_object("time_label");
|
||||
avatar_image = (AvatarImage) builder.get_object("avatar_image");
|
||||
|
@ -65,7 +70,7 @@ public class ConversationItemSkeleton : Plugins.ConversationItemWidgetInterface,
|
|||
}
|
||||
|
||||
private void set_header() {
|
||||
if (!show_skeleton || !item.requires_header) return;
|
||||
if (!show_skeleton) return;
|
||||
|
||||
update_name_label();
|
||||
// name_label.style_updated.connect(update_name_label);
|
||||
|
@ -102,34 +107,32 @@ public class ConversationItemSkeleton : Plugins.ConversationItemWidgetInterface,
|
|||
encryption_image.visible = show_skeleton;
|
||||
received_image.visible = show_skeleton;
|
||||
|
||||
if (show_skeleton) {
|
||||
main_grid.get_style_context().add_class("has-skeleton");
|
||||
if (show_skeleton || content_meta_item == null) {
|
||||
main_grid.add_css_class("has-skeleton");
|
||||
}
|
||||
|
||||
if (last_group_item) {
|
||||
main_grid.get_style_context().add_class("last-group-item");
|
||||
main_grid.add_css_class("last-group-item");
|
||||
}
|
||||
}
|
||||
|
||||
private void update_edit_mode() {
|
||||
if (item.in_edit_mode) {
|
||||
main_grid.get_style_context().add_class("edit-mode");
|
||||
main_grid.add_css_class("edit-mode");
|
||||
} else {
|
||||
main_grid.get_style_context().remove_class("edit-mode");
|
||||
main_grid.remove_css_class("edit-mode");
|
||||
}
|
||||
}
|
||||
|
||||
private void update_error_mode() {
|
||||
if (item_mark == Message.Marked.ERROR) {
|
||||
main_grid.get_style_context().add_class("error");
|
||||
main_grid.add_css_class("error");
|
||||
} else {
|
||||
main_grid.get_style_context().remove_class("error");
|
||||
main_grid.remove_css_class("error");
|
||||
}
|
||||
}
|
||||
|
||||
private void update_encryption_icon() {
|
||||
encryption_image.visible = true;
|
||||
|
||||
Application app = GLib.Application.get_default() as Application;
|
||||
|
||||
ContentMetaItem ci = item as ContentMetaItem;
|
||||
|
@ -141,7 +144,8 @@ public class ConversationItemSkeleton : Plugins.ConversationItemWidgetInterface,
|
|||
break;
|
||||
}
|
||||
}
|
||||
encryption_image.icon_name = icon_name ?? "dino-changes-prevent-symbolic";
|
||||
encryption_image.icon_name = icon_name ?? "changes-prevent-symbolic";
|
||||
encryption_image.visible = true;
|
||||
}
|
||||
|
||||
if (item.encryption == Encryption.NONE) {
|
||||
|
@ -149,6 +153,7 @@ public class ConversationItemSkeleton : Plugins.ConversationItemWidgetInterface,
|
|||
encryption_image.icon_name = "dino-changes-allowed-symbolic";
|
||||
encryption_image.tooltip_text = _("Unencrypted");
|
||||
Util.force_error_color(encryption_image);
|
||||
encryption_image.visible = true;
|
||||
} else if (conversation.encryption == Encryption.NONE) {
|
||||
encryption_image.icon_name = null;
|
||||
encryption_image.visible = false;
|
||||
|
@ -176,8 +181,11 @@ public class ConversationItemSkeleton : Plugins.ConversationItemWidgetInterface,
|
|||
case Message.Marked.READ: received_image.icon_name = "dino-double-tick-symbolic"; break;
|
||||
case Message.Marked.WONTSEND:
|
||||
received_image.icon_name = "dialog-warning-symbolic";
|
||||
received_image.icon_name = _("Unable to send message");
|
||||
// TODO error color on marked icon and time
|
||||
Util.force_error_color(received_image);
|
||||
Util.force_error_color(time_label);
|
||||
string error_text = _("Unable to send message");
|
||||
received_image.tooltip_text = error_text;
|
||||
time_label.tooltip_text = error_text;
|
||||
break;
|
||||
default: received_image.icon_name = null; break;
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
|
|||
|
||||
private void on_leave_notify_event() {
|
||||
if (currently_highlighted != null) {
|
||||
currently_highlighted.get_style_context().remove_class("highlight");
|
||||
currently_highlighted.remove_css_class("highlight");
|
||||
currently_highlighted = null;
|
||||
}
|
||||
message_menu_box.visible = false;
|
||||
|
@ -134,7 +134,7 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
|
|||
}
|
||||
};
|
||||
|
||||
if (currently_highlighted != null) currently_highlighted.get_style_context().remove_class("highlight");
|
||||
if (currently_highlighted != null) currently_highlighted.remove_css_class("highlight");
|
||||
|
||||
currently_highlighted = null;
|
||||
current_meta_item = null;
|
||||
|
@ -160,7 +160,7 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
|
|||
if (current_meta_item != null) {
|
||||
// Highlight widget
|
||||
currently_highlighted = w;
|
||||
currently_highlighted.get_style_context().add_class("highlight");
|
||||
currently_highlighted.add_css_class("highlight");
|
||||
|
||||
// Move message menu
|
||||
message_menu_box.margin_top = (int)(widget_y - 10);
|
||||
|
@ -233,7 +233,7 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
|
|||
i++;
|
||||
}
|
||||
scrolled.vadjustment.value = h - scrolled.vadjustment.page_size * 1/3;
|
||||
w.get_style_context().add_class("highlight-once");
|
||||
w.add_css_class("highlight-once");
|
||||
reload_messages = true;
|
||||
stack.set_visible_child_name("main");
|
||||
return false;
|
||||
|
@ -414,6 +414,7 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug
|
|||
});
|
||||
}
|
||||
} else if (scrolled.vadjustment.value < scrolled.vadjustment.upper - scrolled.vadjustment.page_size - 1) {
|
||||
print("move!\n");
|
||||
scrolled.vadjustment.value = scrolled.vadjustment.upper - was_upper + scrolled.vadjustment.value; // stay at same content
|
||||
}
|
||||
was_upper = scrolled.vadjustment.upper;
|
||||
|
|
|
@ -83,12 +83,12 @@ public class DateSeparatorWidget : Box {
|
|||
visible = true;
|
||||
this.date = date;
|
||||
|
||||
label = new Label("") { use_markup=true, halign=Align.CENTER, hexpand=false, visible=true };
|
||||
label.get_style_context().add_class("dim-label");
|
||||
label = new Label("") { use_markup=true, halign=Align.CENTER, hexpand=false };
|
||||
label.add_css_class("dim-label");
|
||||
|
||||
this.append(new Separator(Orientation.HORIZONTAL) { valign=Align.CENTER, hexpand=true, visible=true });
|
||||
this.append(new Separator(Orientation.HORIZONTAL) { valign=Align.CENTER, hexpand=true });
|
||||
this.append(label);
|
||||
this.append(new Separator(Orientation.HORIZONTAL) { valign=Align.CENTER, hexpand=true, visible=true });
|
||||
this.append(new Separator(Orientation.HORIZONTAL) { valign=Align.CENTER, hexpand=true });
|
||||
|
||||
update_time();
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace Dino.Ui {
|
|||
[GtkTemplate (ui = "/im/dino/Dino/file_default_widget.ui")]
|
||||
public class FileDefaultWidget : Box {
|
||||
|
||||
public signal void clicked();
|
||||
public signal void open_file();
|
||||
public signal void save_file_as();
|
||||
public signal void cancel_download();
|
||||
|
@ -35,6 +36,7 @@ public class FileDefaultWidget : Box {
|
|||
this_motion_events.leave.connect(on_pointer_left_event);
|
||||
|
||||
GestureClick gesture_click_controller = new GestureClick();
|
||||
gesture_click_controller.set_button(1); // listen for left clicks
|
||||
this.add_controller(gesture_click_controller);
|
||||
gesture_click_controller.pressed.connect((n_press, x, y) => {
|
||||
// Check whether the click was inside the file menu. Otherwise, open the file.
|
||||
|
@ -42,7 +44,7 @@ public class FileDefaultWidget : Box {
|
|||
this.translate_coordinates(file_menu, x, y, out x_button, out y_button);
|
||||
if (file_menu.contains(x_button, y_button)) return;
|
||||
|
||||
this.open_file();
|
||||
this.clicked();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ public class FileImageWidget : Box {
|
|||
public FileImageWidget() {
|
||||
this.halign = Align.START;
|
||||
|
||||
this.get_style_context().add_class("file-image-widget");
|
||||
this.add_css_class("file-image-widget");
|
||||
}
|
||||
|
||||
public async void load_from_file(File file, string file_name, int MAX_WIDTH=600, int MAX_HEIGHT=300) throws GLib.Error {
|
||||
|
@ -52,7 +52,7 @@ public class FileImageWidget : Box {
|
|||
file_default_widget_controller = new FileDefaultWidgetController(file_default_widget);
|
||||
file_default_widget_controller.set_file(file, file_name, mime_type);
|
||||
|
||||
Overlay overlay = new Overlay() { visible=true };
|
||||
Overlay overlay = new Overlay();
|
||||
overlay.set_child(image);
|
||||
overlay.add_overlay(file_default_widget);
|
||||
overlay.set_measure_overlay(image, true);
|
||||
|
|
|
@ -19,7 +19,7 @@ public class FileMetaItem : ConversationSummary.ContentMetaItem {
|
|||
public override Object? get_widget(Plugins.ConversationItemWidgetInterface outer, Plugins.WidgetType type) {
|
||||
FileItem file_item = content_item as FileItem;
|
||||
FileTransfer transfer = file_item.file_transfer;
|
||||
return new FileWidget(stream_interactor, transfer) { visible=true };
|
||||
return new FileWidget(stream_interactor, transfer);
|
||||
}
|
||||
|
||||
public override Gee.List<Plugins.MessageAction>? get_item_actions(Plugins.WidgetType type) { return null; }
|
||||
|
@ -70,7 +70,7 @@ public class FileWidget : SizeRequestBox {
|
|||
|
||||
FileImageWidget file_image_widget = null;
|
||||
try {
|
||||
file_image_widget = new FileImageWidget() { visible=true };
|
||||
file_image_widget = new FileImageWidget();
|
||||
yield file_image_widget.load_from_file(file_transfer.get_file(), file_transfer.file_name);
|
||||
|
||||
// If the widget changed in the meanwhile, stop
|
||||
|
@ -86,7 +86,7 @@ public class FileWidget : SizeRequestBox {
|
|||
|
||||
if (state != State.DEFAULT) {
|
||||
if (content != null) this.remove(content);
|
||||
FileDefaultWidget default_file_widget = new FileDefaultWidget() { visible=true };
|
||||
FileDefaultWidget default_file_widget = new FileDefaultWidget();
|
||||
default_widget_controller = new FileDefaultWidgetController(default_file_widget);
|
||||
default_widget_controller.set_file_transfer(file_transfer, stream_interactor);
|
||||
content = default_file_widget;
|
||||
|
@ -129,14 +129,10 @@ public class FileDefaultWidgetController : Object {
|
|||
public FileDefaultWidgetController(FileDefaultWidget widget) {
|
||||
this.widget = widget;
|
||||
|
||||
widget.clicked.connect(on_clicked);
|
||||
widget.open_file.connect(open_file);
|
||||
widget.save_file_as.connect(save_file);
|
||||
widget.cancel_download.connect(cancel_download);
|
||||
|
||||
var gesture_controller = new GestureClick();
|
||||
gesture_controller.set_button(1); // listen for left clicks
|
||||
gesture_controller.released.connect(on_clicked);
|
||||
widget.add_controller(gesture_controller);
|
||||
}
|
||||
|
||||
public void set_file_transfer(FileTransfer file_transfer, StreamInteractor stream_interactor) {
|
||||
|
|
|
@ -1,229 +0,0 @@
|
|||
using Dino.Entities;
|
||||
using Gtk;
|
||||
|
||||
namespace Dino.Ui {
|
||||
public class MessageItemWidget : SizeRequestBin {
|
||||
|
||||
public signal void edit_cancelled();
|
||||
public signal void edit_sent(string text);
|
||||
|
||||
enum AdditionalInfo {
|
||||
NONE,
|
||||
PENDING,
|
||||
DELIVERY_FAILED
|
||||
}
|
||||
|
||||
StreamInteractor stream_interactor;
|
||||
public ContentItem content_item;
|
||||
public Message.Marked marked { get; set; }
|
||||
|
||||
Label label = new Label("") { use_markup=true, xalign=0, selectable=true, wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR, vexpand=true, visible=true };
|
||||
MessageItemEditMode? edit_mode = null;
|
||||
ChatTextViewController? controller = null;
|
||||
AdditionalInfo additional_info = AdditionalInfo.NONE;
|
||||
|
||||
ulong realize_id = -1;
|
||||
ulong style_updated_id = -1;
|
||||
ulong marked_notify_handler_id = -1;
|
||||
|
||||
construct {
|
||||
this.append(label);
|
||||
label.activate_link.connect(on_label_activate_link);
|
||||
this.size_request_mode = SizeRequestMode.HEIGHT_FOR_WIDTH;
|
||||
}
|
||||
|
||||
public MessageItemWidget(StreamInteractor stream_interactor, ContentItem content_item) {
|
||||
this.stream_interactor = stream_interactor;
|
||||
this.content_item = content_item;
|
||||
|
||||
Message message = ((MessageItem) content_item).message;
|
||||
if (message.direction == Message.DIRECTION_SENT && !(message.marked in Message.MARKED_RECEIVED)) {
|
||||
var binding = message.bind_property("marked", this, "marked");
|
||||
marked_notify_handler_id = this.notify["marked"].connect(() => {
|
||||
// Currently "pending", but not anymore
|
||||
if (additional_info == AdditionalInfo.PENDING &&
|
||||
message.marked != Message.Marked.SENDING && message.marked != Message.Marked.UNSENT) {
|
||||
update_label();
|
||||
}
|
||||
|
||||
// Currently "error", but not anymore
|
||||
if (additional_info == AdditionalInfo.DELIVERY_FAILED && message.marked != Message.Marked.ERROR) {
|
||||
update_label();
|
||||
}
|
||||
|
||||
// Currently not error, but should be
|
||||
if (additional_info != AdditionalInfo.DELIVERY_FAILED && message.marked == Message.Marked.ERROR) {
|
||||
update_label();
|
||||
}
|
||||
|
||||
// Nothing bad can happen anymore
|
||||
if (message.marked in Message.MARKED_RECEIVED) {
|
||||
binding.unbind();
|
||||
this.disconnect(marked_notify_handler_id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
update_label();
|
||||
}
|
||||
|
||||
public void set_edit_mode() {
|
||||
|
||||
MessageItem message_item = content_item as MessageItem;
|
||||
Message message = message_item.message;
|
||||
|
||||
if (edit_mode == null) {
|
||||
edit_mode = new MessageItemEditMode();
|
||||
controller = new ChatTextViewController(edit_mode.chat_text_view, stream_interactor);
|
||||
Conversation conversation = message_item.conversation;
|
||||
controller.initialize_for_conversation(conversation);
|
||||
|
||||
edit_mode.cancelled.connect(() => {
|
||||
edit_cancelled();
|
||||
unset_edit_mode();
|
||||
});
|
||||
edit_mode.send.connect(() => {
|
||||
if (((MessageItem) content_item).message.body != edit_mode.chat_text_view.text_view.buffer.text) {
|
||||
edit_sent(edit_mode.chat_text_view.text_view.buffer.text);
|
||||
} else {
|
||||
edit_cancelled();
|
||||
}
|
||||
unset_edit_mode();
|
||||
});
|
||||
}
|
||||
|
||||
edit_mode.chat_text_view.text_view.buffer.text = message.body;
|
||||
|
||||
this.remove(label);
|
||||
this.append(edit_mode);
|
||||
|
||||
edit_mode.chat_text_view.text_view.grab_focus();
|
||||
}
|
||||
|
||||
public void unset_edit_mode() {
|
||||
this.remove(edit_mode);
|
||||
this.append(label);
|
||||
label.grab_focus();
|
||||
label.selectable = false;
|
||||
label.selectable = true;
|
||||
}
|
||||
|
||||
public void update_label() {
|
||||
label.label = generate_markup_text(content_item);
|
||||
}
|
||||
|
||||
private string generate_markup_text(ContentItem item) {
|
||||
MessageItem message_item = item as MessageItem;
|
||||
Conversation conversation = message_item.conversation;
|
||||
Message message = message_item.message;
|
||||
|
||||
bool theme_dependent = false;
|
||||
|
||||
string markup_text = message.body;
|
||||
if (markup_text.length > 10000) {
|
||||
markup_text = markup_text.substring(0, 10000) + " [" + _("Message too long") + "]";
|
||||
}
|
||||
if (message.body.has_prefix("/me ")) {
|
||||
markup_text = markup_text.substring(4);
|
||||
}
|
||||
|
||||
if (conversation.type_ == Conversation.Type.GROUPCHAT) {
|
||||
markup_text = Util.parse_add_markup_theme(markup_text, conversation.nickname, true, true, true, Util.is_dark_theme(this), ref theme_dependent);
|
||||
} else {
|
||||
markup_text = Util.parse_add_markup_theme(markup_text, null, true, true, true, Util.is_dark_theme(this), ref theme_dependent);
|
||||
}
|
||||
|
||||
if (message.body.has_prefix("/me ")) {
|
||||
string display_name = Util.get_participant_display_name(stream_interactor, conversation, message.from);
|
||||
markup_text = @"<i><b>$(Markup.escape_text(display_name))</b> " + markup_text + "</i>";
|
||||
}
|
||||
|
||||
int only_emoji_count = Util.get_only_emoji_count(markup_text);
|
||||
if (only_emoji_count != -1) {
|
||||
string size_str = only_emoji_count < 5 ? "xx-large" : "large";
|
||||
markup_text = @"<span size=\'$size_str\'>" + markup_text + "</span>";
|
||||
}
|
||||
|
||||
string dim_color = Util.is_dark_theme(this) ? "#BDBDBD" : "#707070";
|
||||
|
||||
if (message.edit_to != null) {
|
||||
markup_text += @" <span size='small' color='$dim_color'>(%s)</span>".printf(_("edited"));
|
||||
theme_dependent = true;
|
||||
}
|
||||
|
||||
// Append message status info
|
||||
additional_info = AdditionalInfo.NONE;
|
||||
if (message.direction == Message.DIRECTION_SENT && (message.marked == Message.Marked.SENDING || message.marked == Message.Marked.UNSENT)) {
|
||||
// Append "pending..." iff message has not been sent yet
|
||||
if (message.time.compare(new DateTime.now_utc().add_seconds(-10)) < 0) {
|
||||
markup_text += @" <span size='small' color='$dim_color'>%s</span>".printf(_("pending…"));
|
||||
theme_dependent = true;
|
||||
additional_info = AdditionalInfo.PENDING;
|
||||
} else {
|
||||
int time_diff = (- (int) message.time.difference(new DateTime.now_utc()) / 1000);
|
||||
Timeout.add(10000 - time_diff, () => {
|
||||
update_label();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
} else if (message.direction == Message.DIRECTION_SENT && message.marked == Message.Marked.ERROR) {
|
||||
// Append "delivery failed" if there was a server error
|
||||
string error_color = Util.rgba_to_hex(Util.get_label_pango_color(label, "@error_color"));
|
||||
markup_text += " <span size='small' color='%s'>%s</span>".printf(error_color, _("delivery failed"));
|
||||
theme_dependent = true;
|
||||
additional_info = AdditionalInfo.DELIVERY_FAILED;
|
||||
}
|
||||
|
||||
if (theme_dependent && realize_id == -1) {
|
||||
realize_id = label.realize.connect(update_label);
|
||||
// style_updated_id = label.style_updated.connect(update_label);
|
||||
} else if (!theme_dependent && realize_id != -1) {
|
||||
label.disconnect(realize_id);
|
||||
label.disconnect(style_updated_id);
|
||||
}
|
||||
return markup_text;
|
||||
}
|
||||
|
||||
public static bool on_label_activate_link(string uri) {
|
||||
// Always handle xmpp URIs with Dino
|
||||
if (!uri.has_prefix("xmpp:")) return false;
|
||||
File file = File.new_for_uri(uri);
|
||||
Dino.Application.get_default().open(new File[]{file}, "");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[GtkTemplate (ui = "/im/dino/Dino/message_item_widget_edit_mode.ui")]
|
||||
public class MessageItemEditMode : Box {
|
||||
|
||||
public signal void cancelled();
|
||||
public signal void send();
|
||||
|
||||
[GtkChild] public unowned MenuButton emoji_button;
|
||||
[GtkChild] public unowned ChatTextView chat_text_view;
|
||||
[GtkChild] public unowned Button cancel_button;
|
||||
[GtkChild] public unowned Button send_button;
|
||||
[GtkChild] public unowned Frame frame;
|
||||
|
||||
construct {
|
||||
Util.force_css(frame, "* { border-radius: 3px; }");
|
||||
|
||||
EmojiChooser chooser = new EmojiChooser();
|
||||
chooser.emoji_picked.connect((emoji) => {
|
||||
chat_text_view.text_view.buffer.insert_at_cursor(emoji, emoji.data.length);
|
||||
});
|
||||
emoji_button.set_popover(chooser);
|
||||
|
||||
chat_text_view.text_view.buffer.changed.connect_after(on_text_view_changed);
|
||||
|
||||
cancel_button.clicked.connect(() => cancelled());
|
||||
send_button.clicked.connect(() => send());
|
||||
chat_text_view.cancel_input.connect(() => cancelled());
|
||||
chat_text_view.send_text.connect(() => send());
|
||||
}
|
||||
|
||||
private void on_text_view_changed() {
|
||||
send_button.sensitive = chat_text_view.text_view.buffer.text != "";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,7 +28,7 @@ public class MessageMetaItem : ContentMetaItem {
|
|||
ulong style_updated_id = -1;
|
||||
ulong marked_notify_handler_id = -1;
|
||||
|
||||
public Label label = new Label("") { use_markup=true, xalign=0, selectable=true, wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR, hexpand=true, vexpand=true, can_focus=false };
|
||||
public Label label = new Label("") { use_markup=true, xalign=0, selectable=true, wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR, hexpand=true, vexpand=true };
|
||||
|
||||
public MessageMetaItem(ContentItem content_item, StreamInteractor stream_interactor) {
|
||||
base(content_item);
|
||||
|
|
|
@ -33,9 +33,9 @@ public class SubscriptionNotitication : Object {
|
|||
}
|
||||
|
||||
private void show_notification() {
|
||||
Box box = new Box(Orientation.HORIZONTAL, 5) { visible=true };
|
||||
Button accept_button = new Button.with_label(_("Accept")) { visible=true };
|
||||
Button deny_button = new Button.with_label(_("Deny")) { visible=true };
|
||||
Box box = new Box(Orientation.HORIZONTAL, 5);
|
||||
Button accept_button = new Button.with_label(_("Accept"));
|
||||
Button deny_button = new Button.with_label(_("Deny"));
|
||||
GLib.Application app = GLib.Application.get_default();
|
||||
accept_button.clicked.connect(() => {
|
||||
app.activate_action("accept-subscription", conversation.id);
|
||||
|
@ -45,7 +45,7 @@ public class SubscriptionNotitication : Object {
|
|||
app.activate_action("deny-subscription", conversation.id);
|
||||
conversation_view.remove_notification(box);
|
||||
});
|
||||
box.append(new Label(_("This contact would like to add you to their contact list")) { margin_end=10, visible=true });
|
||||
box.append(new Label(_("This contact would like to add you to their contact list")) { margin_end=10 });
|
||||
box.append(accept_button);
|
||||
box.append(deny_button);
|
||||
conversation_view.add_notification(box);
|
||||
|
|
|
@ -1,245 +0,0 @@
|
|||
using Gtk;
|
||||
using Dino.Entities;
|
||||
using Dino;
|
||||
using Gee;
|
||||
using Pango;
|
||||
using Xmpp;
|
||||
|
||||
namespace Dino.Ui.ConversationList {
|
||||
|
||||
public static ListItemFactory get_item_factory() {
|
||||
SignalListItemFactory item_factory = new SignalListItemFactory();
|
||||
item_factory.setup.connect((list_item) => { on_setup(list_item); });
|
||||
item_factory.bind.connect((list_item) => { on_bind(list_item); });
|
||||
return item_factory;
|
||||
}
|
||||
|
||||
public static void on_setup(ListItem listitem) {
|
||||
listitem.child = new ConversationListRow();
|
||||
}
|
||||
|
||||
public static void on_bind(ListItem listitem) {
|
||||
ConversationViewModel list_model = (ConversationViewModel) listitem.get_item();
|
||||
ConversationListRow view = (ConversationListRow) listitem.get_child();
|
||||
StreamInteractor stream_interactor = list_model.stream_interactor;
|
||||
|
||||
list_model.bind_property("name", view.name_label, "label");
|
||||
list_model.notify["latest-content-item"].connect((obj, _) => {
|
||||
update_content_item(view, list_model.conversation, stream_interactor, ((ConversationViewModel) obj).latest_content_item);
|
||||
});
|
||||
list_model.notify["unread-count"].connect((obj, _) => {
|
||||
update_read(view, list_model.conversation, stream_interactor, (int) obj);
|
||||
});
|
||||
|
||||
view.x_button.clicked.connect(() => list_model.closed() );
|
||||
|
||||
ConversationViewModel view_model = (ConversationViewModel) listitem.get_item();
|
||||
view.name_label.label = view_model.name;
|
||||
if (view_model.latest_content_item != null) {
|
||||
update_content_item(view, view_model.conversation, stream_interactor, view_model.latest_content_item);
|
||||
}
|
||||
update_read(view, view_model.conversation, stream_interactor, view_model.unread_count);
|
||||
}
|
||||
|
||||
private static void update_content_item(ConversationListRow view, Conversation conversation, StreamInteractor stream_interactor, ContentItem last_content_item) {
|
||||
view.time_label.label = get_relative_time(last_content_item.time.to_local());
|
||||
view.image.set_conversation(stream_interactor, conversation);
|
||||
|
||||
Label nick_label = view.nick_label;
|
||||
Label message_label = view.message_label;
|
||||
|
||||
switch (last_content_item.type_) {
|
||||
case MessageItem.TYPE:
|
||||
MessageItem message_item = last_content_item as MessageItem;
|
||||
Message last_message = message_item.message;
|
||||
|
||||
string body = last_message.body;
|
||||
bool me_command = body.has_prefix("/me ");
|
||||
|
||||
/* If we have a /me command, we always show the display
|
||||
* name, and we don't set me_is_me on
|
||||
* get_participant_display_name, since that will return
|
||||
* "Me" (internationalized), whereas /me commands expect to
|
||||
* be in the third person. We also omit the colon in this
|
||||
* case, and strip off the /me prefix itself. */
|
||||
|
||||
if (conversation.type_ == Conversation.Type.GROUPCHAT || me_command) {
|
||||
nick_label.label = Util.get_participant_display_name(stream_interactor, conversation, last_message.from, !me_command);
|
||||
} else if (last_message.direction == Message.DIRECTION_SENT) {
|
||||
nick_label.label = _("Me");
|
||||
} else {
|
||||
nick_label.label = "";
|
||||
}
|
||||
|
||||
if (me_command) {
|
||||
/* Don't slice off the space after /me */
|
||||
body = body.slice("/me".length, body.length);
|
||||
} else if (nick_label.label.length > 0) {
|
||||
/* TODO: Is this valid for RTL languages? */
|
||||
nick_label.label += ": ";
|
||||
}
|
||||
|
||||
message_label.attributes.filter((attr) => attr.equal(attr_style_new(Pango.Style.ITALIC)));
|
||||
message_label.label = Util.summarize_whitespaces_to_space(body);
|
||||
|
||||
break;
|
||||
case FileItem.TYPE:
|
||||
FileItem file_item = last_content_item as FileItem;
|
||||
FileTransfer transfer = file_item.file_transfer;
|
||||
|
||||
if (conversation.type_ == Conversation.Type.GROUPCHAT) {
|
||||
// TODO properly display nick for oneself
|
||||
nick_label.label = Util.get_participant_display_name(stream_interactor, conversation, file_item.file_transfer.from, true) + ": ";
|
||||
} else {
|
||||
nick_label.label = transfer.direction == Message.DIRECTION_SENT ? _("Me") + ": " : "";
|
||||
}
|
||||
|
||||
bool file_is_image = transfer.mime_type != null && transfer.mime_type.has_prefix("image");
|
||||
message_label.attributes.insert(attr_style_new(Pango.Style.ITALIC));
|
||||
if (transfer.direction == Message.DIRECTION_SENT) {
|
||||
message_label.label = (file_is_image ? _("Image sent") : _("File sent") );
|
||||
} else {
|
||||
message_label.label = (file_is_image ? _("Image received") : _("File received") );
|
||||
}
|
||||
break;
|
||||
case CallItem.TYPE:
|
||||
CallItem call_item = (CallItem) last_content_item;
|
||||
Call call = call_item.call;
|
||||
|
||||
nick_label.label = call.direction == Call.DIRECTION_OUTGOING ? _("Me") + ": " : "";
|
||||
message_label.attributes.insert(attr_style_new(Pango.Style.ITALIC));
|
||||
message_label.label = call.direction == Call.DIRECTION_OUTGOING ? _("Outgoing call") : _("Incoming call");
|
||||
break;
|
||||
}
|
||||
nick_label.visible = true;
|
||||
message_label.visible = true;
|
||||
}
|
||||
|
||||
private void update_read(ConversationListRow view, Conversation conversation, StreamInteractor stream_interactor, int num_unread) {
|
||||
Label unread_count_label = view.unread_count_label;
|
||||
Label name_label = view.name_label;
|
||||
Label time_label = view.time_label;
|
||||
Label nick_label = view.nick_label;
|
||||
Label message_label = view.message_label;
|
||||
if (num_unread == 0) {
|
||||
unread_count_label.visible = false;
|
||||
|
||||
name_label.attributes.filter((attr) => attr.equal(attr_weight_new(Weight.BOLD)));
|
||||
time_label.attributes.filter((attr) => attr.equal(attr_weight_new(Weight.BOLD)));
|
||||
nick_label.attributes.filter((attr) => attr.equal(attr_weight_new(Weight.BOLD)));
|
||||
message_label.attributes.filter((attr) => attr.equal(attr_weight_new(Weight.BOLD)));
|
||||
} else {
|
||||
unread_count_label.label = num_unread.to_string();
|
||||
unread_count_label.visible = true;
|
||||
|
||||
if (conversation.get_notification_setting(stream_interactor) == Conversation.NotifySetting.ON) {
|
||||
unread_count_label.get_style_context().add_class("unread-count-notify");
|
||||
unread_count_label.get_style_context().remove_class("unread-count");
|
||||
} else {
|
||||
unread_count_label.get_style_context().add_class("unread-count");
|
||||
unread_count_label.get_style_context().remove_class("unread-count-notify");
|
||||
}
|
||||
|
||||
name_label.attributes.insert(attr_weight_new(Weight.BOLD));
|
||||
time_label.attributes.insert(attr_weight_new(Weight.BOLD));
|
||||
nick_label.attributes.insert(attr_weight_new(Weight.BOLD));
|
||||
message_label.attributes.insert(attr_weight_new(Weight.BOLD));
|
||||
}
|
||||
|
||||
name_label.label = name_label.label; // TODO initializes redrawing, which would otherwise not happen. nicer?
|
||||
time_label.label = time_label.label;
|
||||
nick_label.label = nick_label.label;
|
||||
message_label.label = message_label.label;
|
||||
}
|
||||
|
||||
private Widget generate_tooltip(StreamInteractor stream_interactor, Conversation conversation) {
|
||||
Grid grid = new Grid() { row_spacing=5, column_homogeneous=false, column_spacing=5, margin_start=7, margin_end=7, margin_top=7, margin_bottom=7 };
|
||||
|
||||
Label label = new Label(conversation.counterpart.to_string()) { valign=Align.START, xalign=0, visible=true };
|
||||
label.attributes = new AttrList();
|
||||
label.attributes.insert(attr_weight_new(Weight.BOLD));
|
||||
|
||||
grid.attach(label, 0, 0, 2, 1);
|
||||
|
||||
Gee.List<Jid>? full_jids = stream_interactor.get_module(PresenceManager.IDENTITY).get_full_jids(conversation.counterpart, conversation.account);
|
||||
if (full_jids == null) return grid;
|
||||
|
||||
for (int i = 0; i < full_jids.size; i++) {
|
||||
Jid full_jid = full_jids[i];
|
||||
string? show = stream_interactor.get_module(PresenceManager.IDENTITY).get_last_show(full_jid, conversation.account);
|
||||
if (show == null) continue;
|
||||
|
||||
int i_cache = i;
|
||||
stream_interactor.get_module(EntityInfo.IDENTITY).get_identity.begin(conversation.account, full_jid, (_, res) => {
|
||||
Xep.ServiceDiscovery.Identity? identity = stream_interactor.get_module(EntityInfo.IDENTITY).get_identity.end(res);
|
||||
|
||||
Image image = new Image() { hexpand=false, valign=Align.CENTER, visible=true };
|
||||
if (identity != null && (identity.type_ == Xep.ServiceDiscovery.Identity.TYPE_PHONE || identity.type_ == Xep.ServiceDiscovery.Identity.TYPE_TABLET)) {
|
||||
image.set_from_icon_name("dino-device-phone-symbolic");
|
||||
} else {
|
||||
image.set_from_icon_name("dino-device-desktop-symbolic");
|
||||
}
|
||||
|
||||
if (show == Presence.Stanza.SHOW_AWAY) {
|
||||
Util.force_color(image, "#FF9800");
|
||||
} else if (show == Presence.Stanza.SHOW_XA || show == Presence.Stanza.SHOW_DND) {
|
||||
Util.force_color(image, "#FF5722");
|
||||
} else {
|
||||
Util.force_color(image, "#4CAF50");
|
||||
}
|
||||
|
||||
string? status = null;
|
||||
if (show == Presence.Stanza.SHOW_AWAY) {
|
||||
status = "away";
|
||||
} else if (show == Presence.Stanza.SHOW_XA) {
|
||||
status = "not available";
|
||||
} else if (show == Presence.Stanza.SHOW_DND) {
|
||||
status = "do not disturb";
|
||||
}
|
||||
|
||||
var sb = new StringBuilder();
|
||||
if (identity != null && identity.name != null) {
|
||||
sb.append(identity.name);
|
||||
} else if (full_jid.resourcepart != null) {
|
||||
sb.append(full_jid.resourcepart);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
if (status != null) {
|
||||
sb.append(" <i>(").append(status).append(")</i>");
|
||||
}
|
||||
|
||||
Label resource = new Label(sb.str) { use_markup=true, hexpand=true, xalign=0, visible=true };
|
||||
|
||||
grid.attach(image, 0, i_cache + 1, 1, 1);
|
||||
grid.attach(resource, 1, i_cache + 1, 1, 1);
|
||||
});
|
||||
}
|
||||
return grid;
|
||||
}
|
||||
|
||||
private static string get_relative_time(DateTime datetime) {
|
||||
DateTime now = new DateTime.now_local();
|
||||
TimeSpan timespan = now.difference(datetime);
|
||||
if (timespan > 365 * TimeSpan.DAY) {
|
||||
return datetime.get_year().to_string();
|
||||
} else if (timespan > 7 * TimeSpan.DAY) {
|
||||
// Day and month
|
||||
// xgettext:no-c-format
|
||||
return datetime.format(_("%b %d"));
|
||||
} else if (timespan > 2 * TimeSpan.DAY) {
|
||||
return datetime.format("%a");
|
||||
} else if (datetime.get_day_of_month() != now.get_day_of_month()) {
|
||||
return _("Yesterday");
|
||||
} else if (timespan > 9 * TimeSpan.MINUTE) {
|
||||
return datetime.format(Util.is_24h_format() ?
|
||||
/* xgettext:no-c-format */ /* Time in 24h format (w/o seconds) */ _("%H∶%M") :
|
||||
/* xgettext:no-c-format */ /* Time in 12h format (w/o seconds) */ _("%l∶%M %p"));
|
||||
} else if (timespan > 1 * TimeSpan.MINUTE) {
|
||||
ulong mins = (ulong) (timespan.abs() / TimeSpan.MINUTE);
|
||||
return n("%i min ago", "%i mins ago", mins).printf(mins);
|
||||
} else {
|
||||
return _("Just now");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,141 +0,0 @@
|
|||
using Gtk;
|
||||
using Dino.Entities;
|
||||
using Dino;
|
||||
using Gee;
|
||||
using Xmpp;
|
||||
|
||||
public class Dino.Ui.ConversationViewModel : Object {
|
||||
public signal void closed();
|
||||
|
||||
public StreamInteractor stream_interactor { get; set; }
|
||||
public Conversation conversation { get; set; }
|
||||
public string name { get; set; }
|
||||
public ContentItem? latest_content_item { get; set; }
|
||||
public int unread_count { get; set; }
|
||||
}
|
||||
|
||||
public class Dino.Ui.ConversationListModel : Object, ListModel {
|
||||
|
||||
public signal void closed_conversation(Conversation conversation);
|
||||
|
||||
private HashMap<Conversation, ConversationViewModel> conversation_view_model_hm = new HashMap<Conversation, ConversationViewModel>(Conversation.hash_func, Conversation.equals_func);
|
||||
private ArrayList<ConversationViewModel> view_models = new ArrayList<ConversationViewModel>();
|
||||
private StreamInteractor stream_interactor;
|
||||
|
||||
public ConversationListModel(StreamInteractor stream_interactor) {
|
||||
this.stream_interactor = stream_interactor;
|
||||
|
||||
stream_interactor.get_module(ConversationManager.IDENTITY).conversation_activated.connect(add_conversation);
|
||||
stream_interactor.get_module(ConversationManager.IDENTITY).conversation_deactivated.connect(remove_conversation);
|
||||
stream_interactor.get_module(ContentItemStore.IDENTITY).new_item.connect(on_content_item_received);
|
||||
|
||||
foreach (Conversation conversation in stream_interactor.get_module(ConversationManager.IDENTITY).get_active_conversations()) {
|
||||
var view_model = create_view_model(conversation);
|
||||
view_models.add(view_model);
|
||||
conversation_view_model_hm[conversation] = view_model;
|
||||
}
|
||||
view_models.sort(sort);
|
||||
items_changed(0, 0, get_n_items());
|
||||
|
||||
stream_interactor.get_module(RosterManager.IDENTITY).updated_roster_item.connect((account, jid, roster_item) => {
|
||||
ConversationViewModel? view_model = get_view_model(account, jid, Conversation.Type.CHAT);
|
||||
if (view_model == null) return;
|
||||
view_model.name = Util.get_conversation_display_name(stream_interactor, view_model.conversation);
|
||||
});
|
||||
stream_interactor.get_module(MucManager.IDENTITY).room_info_updated.connect((account, jid) => {
|
||||
ConversationViewModel? view_model = get_view_model(account, jid, Conversation.Type.GROUPCHAT);
|
||||
if (view_model == null) return;
|
||||
view_model.name = Util.get_conversation_display_name(stream_interactor, view_model.conversation);
|
||||
// bubble color might have changed
|
||||
view_model.unread_count = stream_interactor.get_module(ChatInteraction.IDENTITY).get_num_unread(view_model.conversation);
|
||||
});
|
||||
stream_interactor.get_module(MucManager.IDENTITY).private_room_occupant_updated.connect((account, room, occupant) => {
|
||||
ConversationViewModel? view_model = get_view_model(account, room.bare_jid, Conversation.Type.GROUPCHAT);
|
||||
if (view_model == null) return;
|
||||
view_model.name = Util.get_conversation_display_name(stream_interactor, view_model.conversation);
|
||||
});
|
||||
}
|
||||
|
||||
public GLib.Object? get_item (uint position) {
|
||||
if (position >= view_models.size) return null;
|
||||
return view_models[(int)position];
|
||||
}
|
||||
|
||||
public GLib.Type get_item_type () {
|
||||
return GLib.Type.OBJECT;
|
||||
}
|
||||
|
||||
public uint get_n_items () {
|
||||
return view_models.size;
|
||||
}
|
||||
|
||||
private ConversationViewModel create_view_model(Conversation conversation) {
|
||||
var view_model = new ConversationViewModel();
|
||||
view_model.stream_interactor = stream_interactor;
|
||||
view_model.conversation = conversation;
|
||||
view_model.name = Util.get_conversation_display_name(stream_interactor, conversation);
|
||||
view_model.latest_content_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_latest(conversation);
|
||||
view_model.unread_count = stream_interactor.get_module(ChatInteraction.IDENTITY).get_num_unread(conversation);
|
||||
view_model.closed.connect(() => closed_conversation(conversation));
|
||||
|
||||
return view_model;
|
||||
}
|
||||
|
||||
private void add_conversation(Conversation conversation) {
|
||||
var view_model = create_view_model(conversation);
|
||||
|
||||
view_models.add(view_model);
|
||||
conversation_view_model_hm[conversation] = view_model;
|
||||
view_models.sort(sort);
|
||||
|
||||
int idx = view_models.index_of(view_model);
|
||||
items_changed(idx, 0, 1);
|
||||
}
|
||||
|
||||
private async void remove_conversation(Conversation conversation) {
|
||||
ConversationViewModel? view_model = conversation_view_model_hm[conversation];
|
||||
if (view_model == null) return;
|
||||
|
||||
int idx = view_models.index_of(view_model);
|
||||
view_models.remove(view_model);
|
||||
conversation_view_model_hm.unset(conversation);
|
||||
items_changed(idx, 1, 0);
|
||||
}
|
||||
|
||||
private void on_content_item_received(ContentItem item, Conversation conversation) {
|
||||
ConversationViewModel? view_model = conversation_view_model_hm[conversation];
|
||||
if (view_model == null) return;
|
||||
|
||||
view_model.latest_content_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_latest(conversation);
|
||||
view_model.unread_count = stream_interactor.get_module(ChatInteraction.IDENTITY).get_num_unread(conversation);
|
||||
|
||||
view_models.sort(sort);
|
||||
items_changed(0, view_models.size, view_models.size); // TODO better
|
||||
}
|
||||
|
||||
private ConversationViewModel? get_view_model(Account account, Jid jid, Conversation.Type? conversation_ty) {
|
||||
foreach (ConversationViewModel view_model in view_models) {
|
||||
Conversation conversation = view_model.conversation;
|
||||
if (conversation.account.equals(account) && conversation.counterpart.equals(jid)) {
|
||||
if (conversation_ty != null && conversation.type_ != conversation_ty) continue;
|
||||
return view_model;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private int sort(ConversationViewModel vm1, ConversationViewModel vm2) {
|
||||
Conversation c1 = vm1.conversation;
|
||||
Conversation c2 = vm2.conversation;
|
||||
|
||||
if (c1 == null || c2 == null) return 0;
|
||||
if (c1.last_active == null) return -1;
|
||||
if (c2.last_active == null) return 1;
|
||||
|
||||
int comp = c2.last_active.compare(c1.last_active);
|
||||
if (comp != 0) return comp;
|
||||
|
||||
return Util.get_conversation_display_name(stream_interactor, c1)
|
||||
.collate(Util.get_conversation_display_name(stream_interactor, c2));
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
using Gee;
|
||||
using Gdk;
|
||||
using Gtk;
|
||||
using Pango;
|
||||
|
||||
using Dino;
|
||||
using Dino.Entities;
|
||||
using Xmpp;
|
||||
|
||||
[GtkTemplate (ui = "/im/dino/Dino/conversation_row.ui")]
|
||||
public class Dino.Ui.ConversationListRow : ListBoxRow {
|
||||
|
||||
[GtkChild] public unowned AvatarImage image;
|
||||
[GtkChild] public unowned Label name_label;
|
||||
[GtkChild] public unowned Label time_label;
|
||||
[GtkChild] public unowned Label nick_label;
|
||||
[GtkChild] public unowned Label message_label;
|
||||
[GtkChild] public unowned Label unread_count_label;
|
||||
[GtkChild] public unowned Button x_button;
|
||||
[GtkChild] public unowned Revealer time_revealer;
|
||||
[GtkChild] public unowned Revealer xbutton_revealer;
|
||||
[GtkChild] public unowned Revealer unread_count_revealer;
|
||||
[GtkChild] public unowned Revealer main_revealer;
|
||||
|
||||
construct {
|
||||
name_label.attributes = new AttrList();
|
||||
}
|
||||
|
||||
public override void state_flags_changed(StateFlags flags) {
|
||||
StateFlags curr_flags = get_state_flags();
|
||||
if ((curr_flags & StateFlags.PRELIGHT) != 0) {
|
||||
time_revealer.set_reveal_child(false);
|
||||
unread_count_revealer.set_reveal_child(false);
|
||||
xbutton_revealer.set_reveal_child(true);
|
||||
} else {
|
||||
time_revealer.set_reveal_child(true);
|
||||
unread_count_revealer.set_reveal_child(true);
|
||||
xbutton_revealer.set_reveal_child(false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
using Gdk;
|
||||
using Gee;
|
||||
using Gtk;
|
||||
|
||||
|
@ -18,7 +19,7 @@ public class ConversationSelector : Widget {
|
|||
|
||||
public ConversationSelector init(StreamInteractor stream_interactor) {
|
||||
this.stream_interactor = stream_interactor;
|
||||
list_box.insert_after(this, null);
|
||||
list_box.set_parent(this);
|
||||
this.layout_manager = new BinLayout();
|
||||
|
||||
stream_interactor.get_module(ConversationManager.IDENTITY).conversation_activated.connect(add_conversation);
|
||||
|
@ -36,7 +37,7 @@ public class ConversationSelector : Widget {
|
|||
}
|
||||
|
||||
construct {
|
||||
get_style_context().add_class("sidebar");
|
||||
add_css_class("sidebar");
|
||||
list_box.set_header_func(header);
|
||||
list_box.set_sort_func(sort);
|
||||
|
||||
|
@ -78,36 +79,29 @@ public class ConversationSelector : Widget {
|
|||
rows[conversation] = row;
|
||||
list_box.append(row);
|
||||
row.main_revealer.set_reveal_child(true);
|
||||
// drag_dest_set(row, DestDefaults.MOTION, null, Gdk.DragAction.COPY);
|
||||
// drag_dest_set_track_motion(row, true);
|
||||
// row.drag_motion.connect(this.on_drag_motion);
|
||||
// row.drag_leave.connect(this.on_drag_leave);
|
||||
|
||||
// Set up drag motion behaviour (select conversation after timeout)
|
||||
DropControllerMotion drop_motion_controller = new DropControllerMotion();
|
||||
uint drag_timeout = 0;
|
||||
drop_motion_controller.motion.connect((x, y) => {
|
||||
if (drag_timeout != 0) return;
|
||||
drag_timeout = Timeout.add(200, () => {
|
||||
conversation_selected(conversation);
|
||||
drag_timeout = 0;
|
||||
return false;
|
||||
});
|
||||
});
|
||||
drop_motion_controller.leave.connect(() => {
|
||||
if (drag_timeout != 0) {
|
||||
Source.remove(drag_timeout);
|
||||
drag_timeout = 0;
|
||||
}
|
||||
});
|
||||
row.add_controller(drop_motion_controller);
|
||||
}
|
||||
list_box.invalidate_sort();
|
||||
}
|
||||
|
||||
/*public bool on_drag_motion(Widget widget, Gdk.DragContext context,
|
||||
int x, int y, uint time) {
|
||||
if (this.drag_timeout != null)
|
||||
return false;
|
||||
this.drag_timeout = Timeout.add(200, () => {
|
||||
if (widget.get_type().is_a(typeof(ConversationSelectorRow))) {
|
||||
ConversationSelectorRow row = widget as ConversationSelectorRow;
|
||||
conversation_selected(row.conversation);
|
||||
}
|
||||
this.drag_timeout = null;
|
||||
return false;
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
public void on_drag_leave(Widget widget, Gdk.DragContext context, uint time) {
|
||||
if (this.drag_timeout != null) {
|
||||
Source.remove(this.drag_timeout);
|
||||
this.drag_timeout = null;
|
||||
}
|
||||
}*/
|
||||
|
||||
private void select_fallback_conversation(Conversation conversation) {
|
||||
if (list_box.get_selected_row() == rows[conversation]) {
|
||||
int index = rows[conversation].get_index();
|
||||
|
|
|
@ -229,11 +229,11 @@ public class ConversationSelectorRow : ListBoxRow {
|
|||
unread_count_label.visible = true;
|
||||
|
||||
if (conversation.get_notification_setting(stream_interactor) == Conversation.NotifySetting.ON) {
|
||||
unread_count_label.get_style_context().add_class("unread-count-notify");
|
||||
unread_count_label.get_style_context().remove_class("unread-count");
|
||||
unread_count_label.add_css_class("unread-count-notify");
|
||||
unread_count_label.remove_css_class("unread-count");
|
||||
} else {
|
||||
unread_count_label.get_style_context().add_class("unread-count");
|
||||
unread_count_label.get_style_context().remove_class("unread-count-notify");
|
||||
unread_count_label.add_css_class("unread-count");
|
||||
unread_count_label.remove_css_class("unread-count-notify");
|
||||
}
|
||||
|
||||
name_label.attributes.insert(attr_weight_new(Weight.BOLD));
|
||||
|
@ -266,7 +266,7 @@ public class ConversationSelectorRow : ListBoxRow {
|
|||
private Widget generate_tooltip() {
|
||||
Grid grid = new Grid() { row_spacing=5, column_homogeneous=false, column_spacing=5, margin_start=7, margin_end=7, margin_top=7, margin_bottom=7 };
|
||||
|
||||
Label label = new Label(conversation.counterpart.to_string()) { valign=Align.START, xalign=0, visible=true };
|
||||
Label label = new Label(conversation.counterpart.to_string()) { valign=Align.START, xalign=0 };
|
||||
label.attributes = new AttrList();
|
||||
label.attributes.insert(attr_weight_new(Weight.BOLD));
|
||||
|
||||
|
@ -284,7 +284,7 @@ public class ConversationSelectorRow : ListBoxRow {
|
|||
stream_interactor.get_module(EntityInfo.IDENTITY).get_identity.begin(conversation.account, full_jid, (_, res) => {
|
||||
Xep.ServiceDiscovery.Identity? identity = stream_interactor.get_module(EntityInfo.IDENTITY).get_identity.end(res);
|
||||
|
||||
Image image = new Image() { hexpand=false, valign=Align.CENTER, visible=true };
|
||||
Image image = new Image() { hexpand=false, valign=Align.CENTER };
|
||||
if (identity != null && (identity.type_ == Xep.ServiceDiscovery.Identity.TYPE_PHONE || identity.type_ == Xep.ServiceDiscovery.Identity.TYPE_TABLET)) {
|
||||
image.set_from_icon_name("dino-device-phone-symbolic");
|
||||
} else {
|
||||
|
@ -322,7 +322,7 @@ public class ConversationSelectorRow : ListBoxRow {
|
|||
sb.append(" <i>(").append(status).append(")</i>");
|
||||
}
|
||||
|
||||
Label resource = new Label(sb.str) { use_markup=true, hexpand=true, xalign=0, visible=true };
|
||||
Label resource = new Label(sb.str) { use_markup=true, hexpand=true, xalign=0 };
|
||||
|
||||
grid.attach(image, 0, i_cache + 1, 1, 1);
|
||||
grid.attach(resource, 1, i_cache + 1, 1, 1);
|
||||
|
|
|
@ -73,7 +73,6 @@ namespace Dino.Ui {
|
|||
}
|
||||
|
||||
public new void set_conversation(Conversation conversation) {
|
||||
print(@"set_conversation $(conversation.counterpart)\n");
|
||||
this.conversation = conversation;
|
||||
|
||||
update_visibility.begin();
|
||||
|
|
|
@ -31,27 +31,27 @@ public class ConversationTitlebarNoCsd : ConversationTitlebar, Object {
|
|||
}
|
||||
}
|
||||
|
||||
private Box widgets_box = new Box(Orientation.HORIZONTAL, 0) { margin_start=15, valign=Align.END, visible=true };
|
||||
private Label title_label = new Label("") { ellipsize=EllipsizeMode.END, visible=true };
|
||||
private Box widgets_box = new Box(Orientation.HORIZONTAL, 7) { margin_start=15, valign=Align.END };
|
||||
private Label title_label = new Label("") { ellipsize=EllipsizeMode.END };
|
||||
private Label subtitle_label = new Label("") { use_markup=true, ellipsize=EllipsizeMode.END, visible=false };
|
||||
|
||||
construct {
|
||||
Box content_box = new Box(Orientation.HORIZONTAL, 0) { margin_start=15, margin_end=10, hexpand=true, visible=true };
|
||||
Box content_box = new Box(Orientation.HORIZONTAL, 0) { margin_start=15, margin_end=10, hexpand=true };
|
||||
main.append(content_box);
|
||||
|
||||
Box titles_box = new Box(Orientation.VERTICAL, 0) { valign=Align.CENTER, hexpand=true, visible=true };
|
||||
Box titles_box = new Box(Orientation.VERTICAL, 0) { valign=Align.CENTER, hexpand=true };
|
||||
content_box.append(titles_box);
|
||||
|
||||
titles_box.append(title_label);
|
||||
subtitle_label.attributes = new AttrList();
|
||||
subtitle_label.get_style_context().add_class("dim-label");
|
||||
subtitle_label.add_css_class("dim-label");
|
||||
titles_box.append(subtitle_label);
|
||||
|
||||
content_box.append(widgets_box);
|
||||
}
|
||||
|
||||
public ConversationTitlebarNoCsd() {
|
||||
main.get_style_context().add_class("dino-header-right");
|
||||
main.add_css_class("dino-header-right");
|
||||
}
|
||||
|
||||
public void insert_button(Widget button) {
|
||||
|
@ -79,7 +79,7 @@ public class ConversationTitlebarCsd : ConversationTitlebar, Object {
|
|||
titles_box.append(title_label);
|
||||
subtitle_label.attributes = new AttrList();
|
||||
subtitle_label.attributes.insert(Pango.attr_scale_new(Pango.Scale.SMALL));
|
||||
subtitle_label.get_style_context().add_class("dim-label");
|
||||
subtitle_label.add_css_class("dim-label");
|
||||
titles_box.append(subtitle_label);
|
||||
|
||||
header_bar.set_title_widget(titles_box);
|
||||
|
|
|
@ -34,7 +34,7 @@ public class ConversationView : Widget {
|
|||
}
|
||||
|
||||
public void add_overlay_dialog(Widget widget) {
|
||||
Revealer revealer = new Revealer() { transition_type=RevealerTransitionType.CROSSFADE , transition_duration= 100, visible=true };
|
||||
Revealer revealer = new Revealer() { transition_type=RevealerTransitionType.CROSSFADE , transition_duration= 100 };
|
||||
revealer.set_child(widget);
|
||||
|
||||
overlay.add_overlay(revealer);
|
||||
|
@ -43,7 +43,7 @@ public class ConversationView : Widget {
|
|||
white_revealer.visible = true;
|
||||
white_revealer.reveal_child = true;
|
||||
widget.destroy.connect(() => {
|
||||
revealer.destroy(); // GTK4: this.remove_overlay(revealer);
|
||||
overlay.remove_overlay(revealer);
|
||||
white_revealer.reveal_child = false;
|
||||
chat_input.do_focus();
|
||||
});
|
||||
|
|
|
@ -6,15 +6,6 @@ using Dino.Entities;
|
|||
|
||||
namespace Dino.Ui {
|
||||
|
||||
enum Target {
|
||||
URI_LIST,
|
||||
STRING
|
||||
}
|
||||
|
||||
//const TargetEntry[] target_list = {
|
||||
// { "text/uri-list", 0, Target.URI_LIST }
|
||||
//};
|
||||
|
||||
public class ConversationViewController : Object {
|
||||
|
||||
public new string? conversation_display_name { get; set; }
|
||||
|
@ -26,6 +17,7 @@ public class ConversationViewController : Object {
|
|||
private ConversationTitlebar titlebar;
|
||||
public SearchMenuEntry search_menu_entry = new SearchMenuEntry();
|
||||
public ListView list_view = new ListView(null, null);
|
||||
private DropTarget drop_event_controller = new DropTarget(typeof(File), DragAction.COPY );
|
||||
|
||||
private ChatInputController chat_input_controller;
|
||||
private StreamInteractor stream_interactor;
|
||||
|
@ -38,19 +30,27 @@ public class ConversationViewController : Object {
|
|||
this.app = GLib.Application.get_default() as Application;
|
||||
|
||||
this.chat_input_controller = new ChatInputController(view.chat_input, stream_interactor);
|
||||
// chat_input_controller.activate_last_message_correction.connect(view.conversation_frame.activate_last_message_correction);
|
||||
chat_input_controller.activate_last_message_correction.connect(view.conversation_frame.activate_last_message_correction);
|
||||
chat_input_controller.file_picker_selected.connect(open_file_picker);
|
||||
chat_input_controller.clipboard_pasted.connect(on_clipboard_paste);
|
||||
|
||||
view.conversation_frame.init(stream_interactor);
|
||||
|
||||
// drag 'n drop file upload
|
||||
// view.drag_data_received.connect(this.on_drag_data_received);
|
||||
drop_event_controller.on_drop.connect(this.on_drag_data_received);
|
||||
|
||||
// forward key presses
|
||||
// view.chat_input.key_press_event.connect(forward_key_press_to_chat_input);
|
||||
// view.conversation_frame.key_press_event.connect(forward_key_press_to_chat_input);
|
||||
// titlebar.key_press_event.connect(forward_key_press_to_chat_input);
|
||||
var key_controller = new EventControllerKey();
|
||||
key_controller.key_pressed.connect((v, c, s) => forward_key_press_to_chat_input(key_controller, v, c, s));
|
||||
view.conversation_frame.add_controller(key_controller);
|
||||
|
||||
var key_controller2 = new EventControllerKey();
|
||||
key_controller2.key_pressed.connect((v, c, s) => forward_key_press_to_chat_input(key_controller2, v, c, s));
|
||||
view.chat_input.add_controller(key_controller2);
|
||||
|
||||
var key_controller3 = new EventControllerKey();
|
||||
key_controller3.key_pressed.connect((v, c, s) => forward_key_press_to_chat_input(key_controller3, v, c, s));
|
||||
titlebar.get_widget().add_controller(key_controller3);
|
||||
|
||||
// goto-end floating button
|
||||
var vadjustment = view.conversation_frame.scrolled.vadjustment;
|
||||
|
@ -102,17 +102,16 @@ public class ConversationViewController : Object {
|
|||
titlebar.insert_button(button);
|
||||
}
|
||||
|
||||
// AccelGroup accel_group = new AccelGroup();
|
||||
// accel_group.connect(Gdk.Key.U, ModifierType.CONTROL_MASK, AccelFlags.VISIBLE, () => {
|
||||
// if (conversation == null) return false;
|
||||
// stream_interactor.get_module(FileManager.IDENTITY).is_upload_available.begin(conversation, (_, res) => {
|
||||
// if (stream_interactor.get_module(FileManager.IDENTITY).is_upload_available.end(res)) {
|
||||
// open_file_picker();
|
||||
// }
|
||||
// });
|
||||
// return false;
|
||||
// });
|
||||
// ((Gtk.Window)view.get_toplevel()).add_accel_group(accel_group);
|
||||
Shortcut shortcut = new Shortcut(new KeyvalTrigger(Key.U, ModifierType.CONTROL_MASK), new CallbackAction(() => {
|
||||
if (conversation == null) return false;
|
||||
stream_interactor.get_module(FileManager.IDENTITY).is_upload_available.begin(conversation, (_, res) => {
|
||||
if (stream_interactor.get_module(FileManager.IDENTITY).is_upload_available.end(res)) {
|
||||
open_file_picker();
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}));
|
||||
((Gtk.Window)view.get_root()).add_shortcut(shortcut);
|
||||
}
|
||||
|
||||
public void select_conversation(Conversation? conversation, bool default_initialize_conversation) {
|
||||
|
@ -159,10 +158,14 @@ public class ConversationViewController : Object {
|
|||
stream_interactor.get_module(FileManager.IDENTITY).is_upload_available.begin(conversation, (_, res) => {
|
||||
bool upload_available = stream_interactor.get_module(FileManager.IDENTITY).is_upload_available.end(res);
|
||||
chat_input_controller.set_file_upload_active(upload_available);
|
||||
if (upload_available && overlay_dialog == null) {
|
||||
// Gtk.drag_dest_set(view, DestDefaults.ALL, target_list, Gdk.DragAction.COPY);
|
||||
if (conversation.account.bare_jid.to_string().has_prefix("f")) {
|
||||
if (drop_event_controller.widget == null) {
|
||||
view.add_controller(drop_event_controller);
|
||||
}
|
||||
} else {
|
||||
// Gtk.drag_dest_unset(view);
|
||||
if (drop_event_controller.widget != null) {
|
||||
view.remove_controller(drop_event_controller);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -186,48 +189,28 @@ public class ConversationViewController : Object {
|
|||
}
|
||||
}
|
||||
|
||||
private void on_clipboard_paste() {
|
||||
private async void on_clipboard_paste() {
|
||||
Clipboard clipboard = view.get_clipboard();
|
||||
// if (clipboard.wait_is_image_available()) {
|
||||
// clipboard.request_image((_, pixbuf) => {
|
||||
// File file = File.new_for_path(Path.build_filename(FileManager.get_storage_dir(), Xmpp.random_uuid() + ".png"));
|
||||
// try {
|
||||
// FileOutputStream fos = file.create(FileCreateFlags.REPLACE_DESTINATION);
|
||||
// pixbuf.save_to_stream_async.begin(fos, "png", null, () => {
|
||||
// open_send_file_overlay(file);
|
||||
// });
|
||||
// } catch (Error e) {
|
||||
// warning("Could not create file to store pasted image in %s, %s", file.get_path(), e.message);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
Gdk.Texture? texture = yield clipboard.read_texture_async(null); // TODO critical
|
||||
var file_name = Path.build_filename(FileManager.get_storage_dir(), Xmpp.random_uuid() + ".png");
|
||||
texture.save_to_png(file_name);
|
||||
open_send_file_overlay(File.new_for_path(file_name));
|
||||
}
|
||||
|
||||
// private void on_drag_data_received(Widget widget, Gdk.DragContext context, int x, int y, SelectionData selection_data, uint target_type, uint time) {
|
||||
// if ((selection_data != null) && (selection_data.get_length() >= 0)) {
|
||||
// switch (target_type) {
|
||||
// case Target.URI_LIST:
|
||||
// string[] uris = selection_data.get_uris();
|
||||
// // For now we only process the first dragged file
|
||||
// if (uris.length >= 1) {
|
||||
// try {
|
||||
// string file_path = Filename.from_uri(uris[0]);
|
||||
// open_send_file_overlay(File.new_for_path(file_path));
|
||||
// } catch (ConvertError e) {
|
||||
// warning("Could not handle dragged file %s, %s", uris[0], e.message);
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
private bool on_drag_data_received(DropTarget target, Value val, double x, double y) {
|
||||
if (val.type() == typeof(File)) {
|
||||
open_send_file_overlay((File)val);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void open_file_picker() {
|
||||
FileChooserNative chooser = new FileChooserNative(_("Select file"), view.get_root() as Gtk.Window, FileChooserAction.OPEN, _("Select"), _("Cancel"));
|
||||
chooser.response.connect(() => {
|
||||
chooser.response.connect((response) => {
|
||||
if (response == ResponseType.ACCEPT) {
|
||||
open_send_file_overlay(File.new_for_path(chooser.get_file().get_path()));
|
||||
}
|
||||
});
|
||||
chooser.show();
|
||||
}
|
||||
|
@ -272,24 +255,22 @@ public class ConversationViewController : Object {
|
|||
stream_interactor.get_module(FileManager.IDENTITY).send_file.begin(file, conversation);
|
||||
}
|
||||
|
||||
// private bool forward_key_press_to_chat_input(EventKey event) {
|
||||
// if (((Gtk.Window)view.get_toplevel()).get_focus() is TextView) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// // Don't forward / change focus on Control / Alt
|
||||
// if (event.keyval == Gdk.Key.Control_L || event.keyval == Gdk.Key.Control_R ||
|
||||
// event.keyval == Gdk.Key.Alt_L || event.keyval == Gdk.Key.Alt_R) {
|
||||
// return false;
|
||||
// }
|
||||
// // Don't forward / change focus on Control + ...
|
||||
// if ((event.state & ModifierType.CONTROL_MASK) > 0) {
|
||||
// return false;
|
||||
// }
|
||||
// if (view.chat_input.chat_text_view.text_view.key_press_event(event)) {
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
private bool forward_key_press_to_chat_input(EventControllerKey key_controller, uint keyval, uint keycode, Gdk.ModifierType state) {
|
||||
if (view.get_root().get_focus() is TextView) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't forward / change focus on Control / Alt
|
||||
if (keyval == Gdk.Key.Control_L || keyval == Gdk.Key.Control_R ||
|
||||
keyval == Gdk.Key.Alt_L || keyval == Gdk.Key.Alt_R) {
|
||||
return false;
|
||||
}
|
||||
// Don't forward / change focus on Control + ...
|
||||
if ((state & ModifierType.CONTROL_MASK) > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return key_controller.forward(view.chat_input.chat_text_view.text_view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,14 +28,11 @@ public class FileSendOverlay {
|
|||
info_label = (Label) builder.get_object("info_label");
|
||||
|
||||
close_button.clicked.connect(() => {
|
||||
main_box.unparent();
|
||||
main_box.destroy();
|
||||
do_close();
|
||||
});
|
||||
send_button.clicked.connect(() => {
|
||||
send_file();
|
||||
this.close();
|
||||
main_box.unparent();
|
||||
main_box.destroy();
|
||||
do_close();
|
||||
});
|
||||
|
||||
load_file_widget.begin(file, file_info);
|
||||
|
@ -48,12 +45,14 @@ public class FileSendOverlay {
|
|||
}
|
||||
});
|
||||
|
||||
// this.key_release_event.connect((event) => {
|
||||
// if (event.keyval == Gdk.Key.Escape) {
|
||||
// this.destroy();
|
||||
// }
|
||||
// return false;
|
||||
// });
|
||||
var key_events = new EventControllerKey();
|
||||
key_events.key_pressed.connect((keyval) => {
|
||||
if (keyval == Gdk.Key.Escape) {
|
||||
do_close();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
this.main_box.add_controller(key_events);
|
||||
}
|
||||
|
||||
private async void load_file_widget(File file, FileInfo file_info) {
|
||||
|
@ -72,7 +71,7 @@ public class FileSendOverlay {
|
|||
|
||||
Widget? widget = null;
|
||||
if (is_image) {
|
||||
FileImageWidget image_widget = new FileImageWidget() { visible=true };
|
||||
FileImageWidget image_widget = new FileImageWidget();
|
||||
try {
|
||||
yield image_widget.load_from_file(file, file_name);
|
||||
widget = image_widget;
|
||||
|
@ -80,7 +79,7 @@ public class FileSendOverlay {
|
|||
}
|
||||
|
||||
if (widget == null) {
|
||||
FileDefaultWidget default_widget = new FileDefaultWidget() { visible=true };
|
||||
FileDefaultWidget default_widget = new FileDefaultWidget();
|
||||
default_widget.name_label.label = file_name;
|
||||
default_widget.update_file_info(mime_type, FileTransfer.State.COMPLETE, (long)file_info.get_size());
|
||||
widget = default_widget;
|
||||
|
@ -96,6 +95,12 @@ public class FileSendOverlay {
|
|||
can_send = false;
|
||||
}
|
||||
|
||||
private void do_close() {
|
||||
this.close();
|
||||
main_box.unparent();
|
||||
main_box.destroy();
|
||||
}
|
||||
|
||||
public Widget get_widget() {
|
||||
return main_box;
|
||||
}
|
||||
|
|
|
@ -185,7 +185,7 @@ public class GlobalSearch {
|
|||
Gee.List<MessageItem> before_message = stream_interactor.get_module(MessageStorage.IDENTITY).get_messages_before_message(item.conversation, item.message.time, item.message.id, 1);
|
||||
Gee.List<MessageItem> after_message = stream_interactor.get_module(MessageStorage.IDENTITY).get_messages_after_message(item.conversation, item.message.time, item.message.id, 1);
|
||||
|
||||
Box context_box = new Box(Orientation.VERTICAL, 5) { visible=true };
|
||||
Box context_box = new Box(Orientation.VERTICAL, 5);
|
||||
if (before_message != null && before_message.size > 0) {
|
||||
context_box.append(get_context_message_widget(before_message.first()));
|
||||
}
|
||||
|
@ -197,16 +197,16 @@ public class GlobalSearch {
|
|||
context_box.append(get_context_message_widget(after_message.first()));
|
||||
}
|
||||
|
||||
Label date_label = new Label(ConversationSummary.ConversationItemSkeleton.get_relative_time(item.time.to_local())) { xalign=0, visible=true };
|
||||
date_label.get_style_context().add_class("dim-label");
|
||||
Label date_label = new Label(ConversationSummary.ConversationItemSkeleton.get_relative_time(item.time.to_local())) { xalign=0 };
|
||||
date_label.add_css_class("dim-label");
|
||||
|
||||
string display_name = Util.get_conversation_display_name(stream_interactor, item.conversation);
|
||||
string title = item.message.type_ == Message.Type.GROUPCHAT ? _("In %s").printf(display_name) : _("With %s").printf(display_name);
|
||||
Box header_box = new Box(Orientation.HORIZONTAL, 10) { margin_start=7, visible=true };
|
||||
header_box.append(new Label(@"<b>$(Markup.escape_text(title))</b>") { ellipsize=EllipsizeMode.END, xalign=0, use_markup=true, visible=true });
|
||||
Box header_box = new Box(Orientation.HORIZONTAL, 10) { margin_start=7 };
|
||||
header_box.append(new Label(@"<b>$(Markup.escape_text(title))</b>") { ellipsize=EllipsizeMode.END, xalign=0, use_markup=true });
|
||||
header_box.append(date_label);
|
||||
|
||||
Box result_box = new Box(Orientation.VERTICAL, 7) { visible=true };
|
||||
Box result_box = new Box(Orientation.VERTICAL, 7);
|
||||
result_box.append(header_box);
|
||||
result_box.append(context_box);
|
||||
|
||||
|
@ -232,7 +232,7 @@ public class GlobalSearch {
|
|||
text = text.substring(0, 25) + " … " + text.substring(index - 50, 50) + text.substring(index, 100) + " … " + text.substring(text.length - 25, 25);
|
||||
}
|
||||
}
|
||||
Label label = new Label("") { use_markup=true, xalign=0, selectable=true, wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR, vexpand=true, visible=true };
|
||||
Label label = new Label("") { use_markup=true, xalign=0, selectable=true, wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR, vexpand=true };
|
||||
|
||||
// Build regex containing all keywords
|
||||
string regex_str = "(";
|
||||
|
@ -269,7 +269,7 @@ public class GlobalSearch {
|
|||
label.label = markup_text;
|
||||
grid.attach(label, 1, 1, 1, 1);
|
||||
|
||||
Button button = new Button() { has_frame=false, visible=true };
|
||||
Button button = new Button() { has_frame=false };
|
||||
button.clicked.connect(() => {
|
||||
selected_item(item);
|
||||
});
|
||||
|
@ -280,20 +280,20 @@ public class GlobalSearch {
|
|||
private Grid get_context_message_widget(MessageItem item) {
|
||||
Grid grid = get_skeleton(item);
|
||||
grid.margin_start = 7;
|
||||
Label label = new Label(item.message.body.replace("\n", "").replace("\r", "")) { ellipsize=EllipsizeMode.MIDDLE, xalign=0, visible=true };
|
||||
Label label = new Label(item.message.body.replace("\n", "").replace("\r", "")) { ellipsize=EllipsizeMode.MIDDLE, xalign=0 };
|
||||
grid.attach(label, 1, 1, 1, 1);
|
||||
grid.opacity = 0.55;
|
||||
return grid;
|
||||
}
|
||||
|
||||
private Grid get_skeleton(MessageItem item) {
|
||||
AvatarImage image = new AvatarImage() { height=32, width=32, margin_end=7, valign=Align.START, visible=true, allow_gray = false };
|
||||
AvatarImage image = new AvatarImage() { height=32, width=32, margin_end=7, valign=Align.START, allow_gray = false };
|
||||
image.set_conversation_participant(stream_interactor, item.conversation, item.jid);
|
||||
Grid grid = new Grid() { row_homogeneous=false, visible=true };
|
||||
Grid grid = new Grid() { row_homogeneous=false };
|
||||
grid.attach(image, 0, 0, 1, 2);
|
||||
|
||||
string display_name = Util.get_participant_display_name(stream_interactor, item.conversation, item.jid);
|
||||
Label name_label = new Label(display_name) { ellipsize=EllipsizeMode.END, xalign=0, visible=true };
|
||||
Label name_label = new Label(display_name) { ellipsize=EllipsizeMode.END, xalign=0 };
|
||||
name_label.attributes = new AttrList();
|
||||
name_label.attributes.insert(attr_weight_new(Weight.BOLD));
|
||||
grid.attach(name_label, 1, 0, 1, 1);
|
||||
|
|
|
@ -49,7 +49,7 @@ public class MainWindow : Gtk.Window {
|
|||
|
||||
this.title = "Dino";
|
||||
|
||||
this.get_style_context().add_class("dino-main");
|
||||
this.add_css_class("dino-main");
|
||||
|
||||
Gtk.Settings.get_default().notify["gtk-decoration-layout"].connect(set_window_buttons);
|
||||
((Widget)this).realize.connect(set_window_buttons);
|
||||
|
@ -77,7 +77,7 @@ public class MainWindow : Gtk.Window {
|
|||
search_frame.set_child(global_search.get_widget());
|
||||
|
||||
Image conversation_list_placeholder_image = (Image) builder.get_object("conversation_list_placeholder_image");
|
||||
conversation_list_placeholder_image.set_from_pixbuf(new Pixbuf.from_resource("/im/dino/Dino/icons/dino-conversation-list-placeholder-arrow.svg"));
|
||||
conversation_list_placeholder_image.set_from_pixbuf(new Pixbuf.from_resource("/im/dino/Dino/icons/scalable/ui/dino-conversation-list-placeholder-arrow.svg"));
|
||||
}
|
||||
|
||||
private void setup_headerbar() {
|
||||
|
|
|
@ -111,13 +111,6 @@ public class MainWindowController : Object {
|
|||
stream_interactor.get_module(ConversationManager.IDENTITY).conversation_activated.connect(() => update_stack_state());
|
||||
stream_interactor.get_module(ConversationManager.IDENTITY).conversation_deactivated.connect(() => update_stack_state());
|
||||
update_stack_state();
|
||||
|
||||
// AccelGroup accel_group = new AccelGroup();
|
||||
// accel_group.connect(Gdk.Key.F, ModifierType.CONTROL_MASK, AccelFlags.VISIBLE, () => {
|
||||
// window.search_revealer.reveal_child = true;
|
||||
// return false;
|
||||
// });
|
||||
// window.add_accel_group(accel_group);
|
||||
}
|
||||
|
||||
public void select_conversation(Conversation? conversation, bool do_reset_search = true, bool default_initialize_conversation = true) {
|
||||
|
|
|
@ -109,8 +109,8 @@ public class AddAccountDialog : Gtk.Dialog {
|
|||
login_button.clicked.connect(show_sign_in_jid);
|
||||
|
||||
foreach (string server in server_list) {
|
||||
ListBoxRow list_box_row = new ListBoxRow() { visible=true };
|
||||
list_box_row.set_child(new Label(server) { xalign=0, margin_start=7, margin_end=7, visible=true });
|
||||
ListBoxRow list_box_row = new ListBoxRow();
|
||||
list_box_row.set_child(new Label(server) { xalign=0, margin_start=7, margin_end=7 });
|
||||
list_box_jids[list_box_row] = server;
|
||||
server_list_box.append(list_box_row);
|
||||
}
|
||||
|
@ -338,8 +338,8 @@ public class AddAccountDialog : Gtk.Dialog {
|
|||
register_title.label = _("Register on %s").printf(server.to_string());
|
||||
|
||||
if (form.oob != null) {
|
||||
form_box.append(new Label(_("The server requires to sign up through a website")){ visible=true } );
|
||||
form_box.append(new Label(@"<a href=\"$(form.oob)\">$(form.oob)</a>") { use_markup=true, visible=true });
|
||||
form_box.append(new Label(_("The server requires to sign up through a website")));
|
||||
form_box.append(new Label(@"<a href=\"$(form.oob)\">$(form.oob)</a>") { use_markup=true });
|
||||
register_form_continue_label.label = _("Open website");
|
||||
register_form_continue.visible = true;
|
||||
register_form_continue.grab_focus();
|
||||
|
@ -347,23 +347,23 @@ public class AddAccountDialog : Gtk.Dialog {
|
|||
if (form.instructions != null && form.instructions != "") {
|
||||
string markup_instructions = Util.parse_add_markup(form.instructions, null, true, false);
|
||||
form_box.append(new Label(markup_instructions) { use_markup=true, halign=Align.CENTER, xalign=0, margin_top=7,
|
||||
wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR, visible=true });
|
||||
wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR });
|
||||
}
|
||||
foreach (Xep.DataForms.DataForm.Field field in form.fields) {
|
||||
Widget? field_widget = Util.get_data_form_field_widget(field);
|
||||
if (field.label != null && field.label != "" && field_widget != null) {
|
||||
form_box.append(new Label(field.label) { xalign=0, margin_top=7, visible=true });
|
||||
form_box.append(new Label(field.label) { xalign=0, margin_top=7 });
|
||||
form_box.append(field_widget);
|
||||
} else if (field.type_ == Xep.DataForms.DataForm.Type.FIXED && field.get_value_string() != "") {
|
||||
string markup_fixed_field = Util.parse_add_markup(field.get_value_string(), null, true, false);
|
||||
form_box.append(new Label(markup_fixed_field) { use_markup=true, xalign=0, margin_top=7,
|
||||
wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR, visible=true });
|
||||
wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR });
|
||||
}
|
||||
}
|
||||
register_form_continue.visible = true;
|
||||
register_form_continue_label.label = _("Register");
|
||||
} else {
|
||||
form_box.append(new Label(_("Check %s for information on how to sign up").printf(@"<a href=\"http://$(server)\">$(server)</a>")) { use_markup=true, visible=true });
|
||||
form_box.append(new Label(_("Check %s for information on how to sign up").printf(@"<a href=\"http://$(server)\">$(server)</a>")) { use_markup=true });
|
||||
register_form_continue.visible = false;
|
||||
}
|
||||
}
|
||||
|
@ -423,21 +423,19 @@ public class AddAccountDialog : Gtk.Dialog {
|
|||
}
|
||||
|
||||
private void animate_window_resize(Widget widget) { // TODO code duplication
|
||||
// int def_height, curr_width, curr_height;
|
||||
// get_size(out curr_width, out curr_height);
|
||||
// widget.get_preferred_height(null, out def_height);
|
||||
// def_height += 5;
|
||||
// int difference = def_height - curr_height;
|
||||
// Timer timer = new Timer();
|
||||
// Timeout.add((int) (stack.transition_duration / 30),
|
||||
// () => {
|
||||
// ulong microsec;
|
||||
// timer.elapsed(out microsec);
|
||||
// ulong millisec = microsec / 1000;
|
||||
// double partial = double.min(1, (double) millisec / stack.transition_duration);
|
||||
// resize(curr_width, (int) (curr_height + difference * partial));
|
||||
// return millisec < stack.transition_duration;
|
||||
// });
|
||||
int curr_height = widget.get_size(Orientation.VERTICAL);
|
||||
var natural_size = Requisition();
|
||||
stack.get_preferred_size(null, out natural_size);
|
||||
int difference = natural_size.height + 5 - curr_height;
|
||||
Timer timer = new Timer();
|
||||
Timeout.add((int) (stack.transition_duration / 30), () => {
|
||||
ulong microsec;
|
||||
timer.elapsed(out microsec);
|
||||
ulong millisec = microsec / 1000;
|
||||
double partial = double.min(1, (double) millisec / stack.transition_duration);
|
||||
default_height = (int) (curr_height + difference * partial);
|
||||
return millisec < stack.transition_duration;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,8 +58,8 @@ public class Dialog : Gtk.Dialog {
|
|||
Widget? widget = e.get_widget(Plugins.WidgetType.GTK4) as Widget;
|
||||
if (widget == null) continue;
|
||||
|
||||
Label label = new Label(e.name) { xalign=1, yalign=0, visible=true };
|
||||
label.get_style_context().add_class("dim-label");
|
||||
Label label = new Label(e.name) { xalign=1, yalign=0 };
|
||||
label.add_css_class("dim-label");
|
||||
label.margin_top = e.label_top_padding == -1 ? default_top_padding : e.label_top_padding;
|
||||
settings_list.attach(label, 0, row_index);
|
||||
|
||||
|
@ -117,8 +117,9 @@ public class Dialog : Gtk.Dialog {
|
|||
msg.secondary_text = "You won't be able to access your conversation history anymore."; // TODO remove history!
|
||||
Button ok_button = msg.get_widget_for_response(ResponseType.OK) as Button;
|
||||
ok_button.label = _("Remove");
|
||||
ok_button.get_style_context().add_class("destructive-action");
|
||||
if (/*msg.run() == Gtk.ResponseType.OK*/ true) {
|
||||
ok_button.add_css_class("destructive-action");
|
||||
msg.response.connect((response) => {
|
||||
if (response == ResponseType.OK) {
|
||||
account_list.remove(account_item);
|
||||
if (account_item.account.enabled) account_disabled(account_item.account);
|
||||
account_item.account.remove();
|
||||
|
@ -129,6 +130,8 @@ public class Dialog : Gtk.Dialog {
|
|||
}
|
||||
}
|
||||
msg.close();
|
||||
});
|
||||
msg.present();
|
||||
}
|
||||
|
||||
private void on_account_list_row_selected(ListBoxRow? row) {
|
||||
|
@ -205,7 +208,7 @@ public class Dialog : Gtk.Dialog {
|
|||
ConnectionManager.ConnectionError? error = stream_interactor.connection_manager.get_error(account);
|
||||
if (error != null) {
|
||||
state_label.label = get_connection_error_description(error);
|
||||
state_label.get_style_context().add_class("is_error");
|
||||
state_label.add_css_class("is_error");
|
||||
} else {
|
||||
ConnectionManager.ConnectionState state = stream_interactor.connection_manager.get_state(account);
|
||||
switch (state) {
|
||||
|
@ -216,7 +219,7 @@ public class Dialog : Gtk.Dialog {
|
|||
case ConnectionManager.ConnectionState.DISCONNECTED:
|
||||
state_label.label = _("Disconnected"); break;
|
||||
}
|
||||
state_label.get_style_context().remove_class("is_error");
|
||||
state_label.remove_css_class("is_error");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -122,16 +122,16 @@ public class List : Box {
|
|||
if (aff == affiliation) count++;
|
||||
}
|
||||
|
||||
Label title_label = new Label("") { margin_start=10, xalign=0, visible=true };
|
||||
Label title_label = new Label("") { margin_start=10, xalign=0 };
|
||||
title_label.set_markup(@"<b>$(Markup.escape_text(aff_str))</b>");
|
||||
|
||||
Label count_label = new Label(@"$count") { xalign=0, margin_end=7, hexpand=true, visible=true };
|
||||
count_label.get_style_context().add_class("dim-label");
|
||||
Label count_label = new Label(@"$count") { xalign=0, margin_end=7, hexpand=true };
|
||||
count_label.add_css_class("dim-label");
|
||||
|
||||
Grid grid = new Grid() { margin_top=top?5:15, column_spacing=5, hexpand=true, visible=true };
|
||||
Grid grid = new Grid() { margin_top=top?5:15, column_spacing=5, hexpand=true };
|
||||
grid.attach(title_label, 0, 0, 1, 1);
|
||||
grid.attach(count_label, 1, 0, 1, 1);
|
||||
grid.attach(new Separator(Orientation.HORIZONTAL) { hexpand=true, vexpand=true, visible=true }, 0, 1, 2, 1);
|
||||
grid.attach(new Separator(Orientation.HORIZONTAL) { hexpand=true, vexpand=true }, 0, 1, 2, 1);
|
||||
return grid;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,10 +10,10 @@ public class View : Popover {
|
|||
private StreamInteractor stream_interactor;
|
||||
private Conversation conversation;
|
||||
|
||||
private Stack stack = new Stack() { vhomogeneous=false, visible=true };
|
||||
private Box list_box = new Box(Orientation.VERTICAL, 1) { visible=true };
|
||||
private Stack stack = new Stack() { vhomogeneous=false };
|
||||
private Box list_box = new Box(Orientation.VERTICAL, 1);
|
||||
private List? list = null;
|
||||
private ListBox invite_list = new ListBox() { visible=true };
|
||||
private ListBox invite_list = new ListBox();
|
||||
private Box? jid_menu = null;
|
||||
|
||||
private Jid? selected_jid;
|
||||
|
@ -25,6 +25,7 @@ public class View : Popover {
|
|||
this.show.connect(initialize_list);
|
||||
|
||||
invite_list.append(new ListRow.label("+", _("Invite")).get_widget());
|
||||
invite_list.can_focus = false;
|
||||
list_box.append(invite_list);
|
||||
invite_list.row_activated.connect(on_invite_clicked);
|
||||
|
||||
|
@ -44,7 +45,7 @@ public class View : Popover {
|
|||
|
||||
private void initialize_list() {
|
||||
if (list == null) {
|
||||
list = new List(stream_interactor, conversation) { visible=true };
|
||||
list = new List(stream_interactor, conversation);
|
||||
list_box.prepend(list);
|
||||
|
||||
list.list_box.row_activated.connect((row) => {
|
||||
|
@ -68,17 +69,17 @@ public class View : Popover {
|
|||
Jid? real_jid = stream_interactor.get_module(MucManager.IDENTITY).get_real_jid(jid, conversation.account);
|
||||
if (real_jid != null) name += "\n<span font=\'8\'>%s</span>".printf(Markup.escape_text(real_jid.bare_jid.to_string()));
|
||||
|
||||
Box header_box = new Box(Orientation.HORIZONTAL, 5) { visible=true };
|
||||
header_box.append(new Image.from_icon_name("pan-start-symbolic") { visible=true });
|
||||
header_box.append(new Label(name) { xalign=0, use_markup=true, hexpand=true, visible=true });
|
||||
Button header_button = new Button() { has_frame=false, visible=true };
|
||||
Box header_box = new Box(Orientation.HORIZONTAL, 5);
|
||||
header_box.append(new Image.from_icon_name("pan-start-symbolic"));
|
||||
header_box.append(new Label(name) { xalign=0, use_markup=true, hexpand=true });
|
||||
Button header_button = new Button() { has_frame=false };
|
||||
header_button.child = header_box;
|
||||
|
||||
Box outer_box = new Box(Orientation.VERTICAL, 5) { visible=true };
|
||||
Box outer_box = new Box(Orientation.VERTICAL, 5);
|
||||
outer_box.append(header_button);
|
||||
header_button.clicked.connect(show_list);
|
||||
|
||||
Button private_button = new Button.with_label(_("Start private conversation")) { visible=true };
|
||||
Button private_button = new Button.with_label(_("Start private conversation")) ;
|
||||
outer_box.append(private_button);
|
||||
private_button.clicked.connect(private_conversation_button_clicked);
|
||||
|
||||
|
@ -86,19 +87,19 @@ public class View : Popover {
|
|||
Xmpp.Xep.Muc.Role? role = stream_interactor.get_module(MucManager.IDENTITY).get_role(own_jid, conversation.account);
|
||||
|
||||
if (role == Xmpp.Xep.Muc.Role.MODERATOR && stream_interactor.get_module(MucManager.IDENTITY).kick_possible(conversation.account, jid)) {
|
||||
Button kick_button = new Button.with_label(_("Kick")) { visible=true };
|
||||
Button kick_button = new Button.with_label(_("Kick")) ;
|
||||
outer_box.append(kick_button);
|
||||
kick_button.clicked.connect(kick_button_clicked);
|
||||
}
|
||||
if (stream_interactor.get_module(MucManager.IDENTITY).is_moderated_room(conversation.account, conversation.counterpart) && role == Xmpp.Xep.Muc.Role.MODERATOR){
|
||||
if (stream_interactor.get_module(MucManager.IDENTITY).get_role(selected_jid, conversation.account) == Xmpp.Xep.Muc.Role.VISITOR) {
|
||||
Button voice_button = new Button.with_label(_("Grant write permission")) { visible=true };
|
||||
Button voice_button = new Button.with_label(_("Grant write permission")) ;
|
||||
outer_box.append(voice_button);
|
||||
voice_button.clicked.connect(() =>
|
||||
voice_button_clicked("participant"));
|
||||
}
|
||||
else if (stream_interactor.get_module(MucManager.IDENTITY).get_role(selected_jid, conversation.account) == Xmpp.Xep.Muc.Role.PARTICIPANT){
|
||||
Button voice_button = new Button.with_label(_("Revoke write permission")) { visible=true };
|
||||
Button voice_button = new Button.with_label(_("Revoke write permission")) ;
|
||||
outer_box.append(voice_button);
|
||||
voice_button.clicked.connect(() =>
|
||||
voice_button_clicked("visitor"));
|
||||
|
|
|
@ -11,7 +11,7 @@ public static Widget? get_data_form_field_widget(DataForms.DataForm.Field field)
|
|||
switch (field.type_) {
|
||||
case DataForms.DataForm.Type.BOOLEAN:
|
||||
DataForms.DataForm.BooleanField boolean_field = field as DataForms.DataForm.BooleanField;
|
||||
Switch sw = new Switch() { active=boolean_field.value, halign=Align.START, valign=Align.CENTER, visible=true };
|
||||
Switch sw = new Switch() { active=boolean_field.value, halign=Align.START, valign=Align.CENTER };
|
||||
sw.state_set.connect((state) => {
|
||||
boolean_field.value = state;
|
||||
return false;
|
||||
|
@ -21,7 +21,7 @@ public static Widget? get_data_form_field_widget(DataForms.DataForm.Field field)
|
|||
return null;
|
||||
case DataForms.DataForm.Type.LIST_SINGLE:
|
||||
DataForms.DataForm.ListSingleField list_single_field = field as DataForms.DataForm.ListSingleField;
|
||||
ComboBoxText combobox = new ComboBoxText() { valign=Align.CENTER, visible=true };
|
||||
ComboBoxText combobox = new ComboBoxText() { valign=Align.CENTER };
|
||||
for (int i = 0; i < list_single_field.options.size; i++) {
|
||||
DataForms.DataForm.Option option = list_single_field.options[i];
|
||||
combobox.append(option.value, option.label);
|
||||
|
@ -35,7 +35,7 @@ public static Widget? get_data_form_field_widget(DataForms.DataForm.Field field)
|
|||
return null;
|
||||
case DataForms.DataForm.Type.TEXT_PRIVATE:
|
||||
DataForms.DataForm.TextPrivateField text_private_field = field as DataForms.DataForm.TextPrivateField;
|
||||
Entry entry = new Entry() { text=text_private_field.value ?? "", valign=Align.CENTER, visible=true, visibility=false };
|
||||
Entry entry = new Entry() { text=text_private_field.value ?? "", valign=Align.CENTER, visibility=false };
|
||||
var entry_key_events = new EventControllerKey();
|
||||
entry_key_events.key_released.connect(() => {
|
||||
text_private_field.value = entry.text;
|
||||
|
@ -44,7 +44,7 @@ public static Widget? get_data_form_field_widget(DataForms.DataForm.Field field)
|
|||
return entry;
|
||||
case DataForms.DataForm.Type.TEXT_SINGLE:
|
||||
DataForms.DataForm.TextSingleField text_single_field = field as DataForms.DataForm.TextSingleField;
|
||||
Entry entry = new Entry() { text=text_single_field.value ?? "", valign=Align.CENTER, visible=true };
|
||||
Entry entry = new Entry() { text=text_single_field.value ?? "", valign=Align.CENTER };
|
||||
var entry_key_events = new EventControllerKey();
|
||||
entry_key_events.key_released.connect(() => {
|
||||
text_single_field.value = entry.text;
|
||||
|
|
|
@ -6,12 +6,12 @@ namespace Dino.Ui.Util {
|
|||
public class LabelHybrid : Widget {
|
||||
|
||||
public Stack stack = new Stack();
|
||||
public Label label = new Label("") { visible=true, max_width_chars=1, ellipsize=Pango.EllipsizeMode.END };
|
||||
protected Button button = new Button() { has_frame=false, visible=true };
|
||||
public Label label = new Label("") { max_width_chars=1, ellipsize=Pango.EllipsizeMode.END };
|
||||
protected Button button = new Button() { has_frame=false };
|
||||
|
||||
internal virtual void init(Widget widget) {
|
||||
this.layout_manager = new BinLayout();
|
||||
stack.insert_after(this, null);
|
||||
stack.set_parent(this);
|
||||
button.child = label;
|
||||
stack.add_named(button, "label");
|
||||
stack.add_named(widget, "widget");
|
||||
|
@ -29,6 +29,10 @@ public class LabelHybrid : Widget {
|
|||
public void show_label() {
|
||||
stack.visible_child_name = "label";
|
||||
}
|
||||
|
||||
public override void dispose() {
|
||||
stack.unparent();
|
||||
}
|
||||
}
|
||||
|
||||
public class EntryLabelHybrid : LabelHybrid {
|
||||
|
@ -58,7 +62,7 @@ public class EntryLabelHybrid : LabelHybrid {
|
|||
public Entry entry {
|
||||
get {
|
||||
if (entry_ == null) {
|
||||
entry_ = new Entry() { visible=true };
|
||||
entry_ = new Entry();
|
||||
init(entry_);
|
||||
}
|
||||
return entry_;
|
||||
|
@ -71,10 +75,11 @@ public class EntryLabelHybrid : LabelHybrid {
|
|||
}
|
||||
|
||||
internal override void init(Widget widget) {
|
||||
Entry? e = widget as Entry; if (e == null) return;
|
||||
Entry? e = widget as Entry;
|
||||
if (e == null) return;
|
||||
entry = e;
|
||||
base.init(entry);
|
||||
update_label();
|
||||
set_label_label(entry.text);
|
||||
|
||||
var key_events = new EventControllerKey();
|
||||
key_events.key_released.connect(on_key_released);
|
||||
|
@ -106,10 +111,6 @@ public class EntryLabelHybrid : LabelHybrid {
|
|||
label.label = filler;
|
||||
}
|
||||
}
|
||||
|
||||
private void update_label() {
|
||||
text = text;
|
||||
}
|
||||
}
|
||||
|
||||
public class ComboBoxTextLabelHybrid : LabelHybrid {
|
||||
|
@ -128,7 +129,7 @@ public class ComboBoxTextLabelHybrid : LabelHybrid {
|
|||
public ComboBoxText combobox {
|
||||
get {
|
||||
if (combobox_ == null) {
|
||||
combobox_ = new ComboBoxText() { visible=true };
|
||||
combobox_ = new ComboBoxText();
|
||||
init(combobox_);
|
||||
}
|
||||
return combobox_;
|
||||
|
|
|
@ -177,20 +177,6 @@ class ScalingImage : Widget {
|
|||
minimum_baseline = natural_baseline = -1;
|
||||
}
|
||||
|
||||
// public override void get_preferred_height_for_width(int width, out int minimum_height, out int natural_height) {
|
||||
// double exact_width = width, exact_height = -1;
|
||||
// calculate_size(ref exact_width, ref exact_height);
|
||||
// natural_height = (int) Math.ceil(exact_height);
|
||||
// minimum_height = natural_height;
|
||||
// }
|
||||
//
|
||||
// public override void get_preferred_width_for_height(int height, out int minimum_width, out int natural_width) {
|
||||
// double exact_width = -1, exact_height = height;
|
||||
// calculate_size(ref exact_width, ref exact_height);
|
||||
// natural_width = (int) Math.ceil(exact_width);
|
||||
// minimum_width = natural_width;
|
||||
// }
|
||||
|
||||
public override SizeRequestMode get_request_mode() {
|
||||
return SizeRequestMode.HEIGHT_FOR_WIDTH;
|
||||
}
|
||||
|
|
|
@ -33,5 +33,10 @@ public class SizingBin : Widget {
|
|||
natural = int.max(natural, minimum);
|
||||
}
|
||||
}
|
||||
|
||||
public override void dispose() {
|
||||
var child = this.get_first_child();
|
||||
if (child != null) child.unparent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -236,7 +236,6 @@
|
|||
<property name="position">left</property>
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
|
|
|
@ -159,8 +159,8 @@ public class BadMessagesWidget : Box {
|
|||
} else {
|
||||
warning_text += _("%s does not trust this device. That means, you might be missing messages.").printf(who);
|
||||
}
|
||||
Label label = new Label(warning_text) { margin_start=70, margin_end=70, justify=Justification.CENTER, use_markup=true, selectable=true, wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR, hexpand=true, visible=true };
|
||||
label.get_style_context().add_class("dim-label");
|
||||
Label label = new Label(warning_text) { margin_start=70, margin_end=70, justify=Justification.CENTER, use_markup=true, selectable=true, wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR, hexpand=true };
|
||||
label.add_css_class("dim-label");
|
||||
this.append(label);
|
||||
|
||||
label.activate_link.connect(() => {
|
||||
|
|
|
@ -109,7 +109,7 @@ public class ContactDetailsDialog : Gtk.Dialog {
|
|||
qrcode_image.set_from_pixbuf(qr_pixbuf);
|
||||
qrcode_image.margin_top = qrcode_image.margin_end =
|
||||
qrcode_image.margin_bottom = qrcode_image.margin_start = QUIET_ZONE_MODULES*MODULE_SIZE_PX;
|
||||
qrcode_popover.get_style_context().add_class("qrcode-container");
|
||||
qrcode_popover.add_css_class("qrcode-container");
|
||||
|
||||
show_qrcode_button.popover = qrcode_popover;
|
||||
}
|
||||
|
@ -260,12 +260,12 @@ public class ContactDetailsDialog : Gtk.Dialog {
|
|||
|
||||
Button accept_button = new Button() { visible = true, valign = Align.CENTER, hexpand = true };
|
||||
accept_button.set_icon_name("emblem-ok-symbolic"); // using .image = sets .image-button. Together with .suggested/destructive action that breaks the button Adwaita
|
||||
accept_button.get_style_context().add_class("suggested-action");
|
||||
accept_button.add_css_class("suggested-action");
|
||||
accept_button.tooltip_text = _("Accept key");
|
||||
|
||||
Button reject_button = new Button() { visible = true, valign = Align.CENTER, hexpand = true };
|
||||
reject_button.set_icon_name("action-unavailable-symbolic");
|
||||
reject_button.get_style_context().add_class("destructive-action");
|
||||
reject_button.add_css_class("destructive-action");
|
||||
reject_button.tooltip_text = _("Reject key");
|
||||
|
||||
accept_button.clicked.connect(() => {
|
||||
|
@ -285,13 +285,13 @@ public class ContactDetailsDialog : Gtk.Dialog {
|
|||
});
|
||||
|
||||
string res = fingerprint_markup(fingerprint_from_base64(device[plugin.db.identity_meta.identity_key_public_base64]));
|
||||
Label fingerprint_label = new Label(res) { use_markup=true, justify=Justification.RIGHT, visible=true, halign = Align.START, valign = Align.CENTER, hexpand = false };
|
||||
Label fingerprint_label = new Label(res) { use_markup=true, justify=Justification.RIGHT, halign = Align.START, valign = Align.CENTER, hexpand = false };
|
||||
box.append(fingerprint_label);
|
||||
|
||||
Box control_box = new Box(Gtk.Orientation.HORIZONTAL, 0) { visible = true, hexpand = true };
|
||||
control_box.append(accept_button);
|
||||
control_box.append(reject_button);
|
||||
control_box.get_style_context().add_class("linked"); // .linked: Visually link the accept / reject buttons
|
||||
control_box.add_css_class("linked"); // .linked: Visually link the accept / reject buttons
|
||||
box.append(control_box);
|
||||
|
||||
lbr.set_child(box);
|
||||
|
@ -304,7 +304,7 @@ public class ContactDetailsDialog : Gtk.Dialog {
|
|||
public class FingerprintRow : ListBoxRow {
|
||||
|
||||
private Image trust_image = new Image() { visible = true, halign = Align.END };
|
||||
private Label fingerprint_label = new Label("") { use_markup=true, justify=Justification.RIGHT, visible=true, halign = Align.START, valign = Align.CENTER, hexpand = false };
|
||||
private Label fingerprint_label = new Label("") { use_markup=true, justify=Justification.RIGHT, halign = Align.START, valign = Align.CENTER, hexpand = false };
|
||||
private Label trust_label = new Label(null) { visible = true, hexpand = true, xalign = 0 };
|
||||
|
||||
public Row row;
|
||||
|
@ -333,17 +333,17 @@ public class FingerprintRow : ListBoxRow {
|
|||
case TrustLevel.TRUSTED:
|
||||
trust_image.icon_name = "emblem-ok-symbolic";
|
||||
trust_label.set_markup("<span color='#1A63D9'>%s</span>".printf(_("Accepted")));
|
||||
fingerprint_label.get_style_context().remove_class("dim-label");
|
||||
fingerprint_label.remove_css_class("dim-label");
|
||||
break;
|
||||
case TrustLevel.UNTRUSTED:
|
||||
trust_image.icon_name = "action-unavailable-symbolic";
|
||||
trust_label.set_markup("<span color='#D91900'>%s</span>".printf(_("Rejected")));
|
||||
fingerprint_label.get_style_context().add_class("dim-label");
|
||||
fingerprint_label.add_css_class("dim-label");
|
||||
break;
|
||||
case TrustLevel.VERIFIED:
|
||||
trust_image.icon_name = "security-high-symbolic";
|
||||
trust_label.set_markup("<span color='#1A63D9'>%s</span>".printf(_("Verified")));
|
||||
fingerprint_label.get_style_context().remove_class("dim-label");
|
||||
fingerprint_label.remove_css_class("dim-label");
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -69,8 +69,8 @@ private class ConversationNotification : MetaConversationNotification {
|
|||
this.jid = jid;
|
||||
this.account = account;
|
||||
|
||||
Box box = new Box(Orientation.HORIZONTAL, 5) { visible=true };
|
||||
Button manage_button = new Button.with_label(_("Manage")) { visible=true };
|
||||
Box box = new Box(Orientation.HORIZONTAL, 5);
|
||||
Button manage_button = new Button.with_label(_("Manage"));
|
||||
manage_button.clicked.connect(() => {
|
||||
manage_button.activate();
|
||||
ContactDetailsDialog dialog = new ContactDetailsDialog(plugin, account, jid);
|
||||
|
@ -80,7 +80,7 @@ private class ConversationNotification : MetaConversationNotification {
|
|||
});
|
||||
dialog.present();
|
||||
});
|
||||
box.append(new Label(_("This contact has new devices")) { margin_end=10, visible=true });
|
||||
box.append(new Label(_("This contact has new devices")) { margin_end=10 });
|
||||
box.append(manage_button);
|
||||
widget = box;
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ public class ManageKeyDialog : Gtk.Dialog {
|
|||
Pango.AttrList desc_attrs = new Pango.AttrList();
|
||||
desc_attrs.insert(Pango.attr_scale_new(0.8));
|
||||
lbl_desc.attributes = desc_attrs;
|
||||
lbl_desc.get_style_context().add_class("dim-label");
|
||||
lbl_desc.add_css_class("dim-label");
|
||||
|
||||
box.append(lbl_title);
|
||||
box.append(lbl_desc);
|
||||
|
|
|
@ -17,7 +17,7 @@ public class ContactDetailsProvider : Plugins.ContactDetailsProvider, Object {
|
|||
if (conversation.type_ == Conversation.Type.CHAT && type == WidgetType.GTK4) {
|
||||
string? key_id = stream_interactor.get_module(Manager.IDENTITY).get_key_id(conversation.account, conversation.counterpart);
|
||||
if (key_id != null) {
|
||||
Label label = new Label("") { use_markup=true, justify=Justification.RIGHT, selectable=true, visible=true };
|
||||
Label label = new Label("") { use_markup=true, justify=Justification.RIGHT, selectable=true };
|
||||
Gee.List<GPG.Key>? keys = null;
|
||||
try {
|
||||
keys = GPGHelper.get_keylist(key_id);
|
||||
|
|
|
@ -45,7 +45,7 @@ public class Dino.Plugins.Rtp.Paintable : Gdk.Paintable, Object {
|
|||
image.get_intrinsic_height() != paintable.get_intrinsic_height() ||
|
||||
image.get_intrinsic_aspect_ratio() != paintable.get_intrinsic_aspect_ratio();
|
||||
|
||||
this.image.dispose();
|
||||
if (image != null) this.image.dispose();
|
||||
this.image = paintable;
|
||||
this.pixel_aspect_ratio = pixel_aspect_ratio;
|
||||
|
||||
|
|