10 Commits

Author SHA1 Message Date
58208b81f2 Fix away tracking
(cherry picked from commit 87410aea50)
2026-09-15 13:04:10 -06:00
e7631701ce release: prepare 2.19.1 2026-09-15 09:28:29 -06:00
b5c3be8ff1 defer channel tree scrolling until realized
(cherry picked from commit e94ffd9d79)
2026-09-15 09:12:34 -06:00
2b9a39783b fix theme service tests
(cherry picked from commit ff4217c3d1)
2026-09-15 09:12:30 -06:00
Christopher Byrne
ecdb462ff8 meson.build: Reflect usage of 0.59 Meson features
src/fe-gtk/meson.build calls feature_opt.allowed() which wasn't
added until 0.59.

Signed-off-by: Christopher Byrne <salah.coronya@gmail.com>
(cherry picked from commit 5018a3a848)
2026-09-15 09:12:25 -06:00
Christopher Byrne
78eb1882cb data/misc/meson.build: Fix referencing possibly undefined variable "appstreamcli"
If meson is passed -Dinstall-plugin-metainfo=false, the "appstreamcli"
will not be defined, but it is later referenced in global scope, which
causes and "undefined variable" error in Meson

Signed-off-by: Christopher Byrne <salah.coronya@gmail.com>
(cherry picked from commit df1c74a91d)
2026-09-15 09:12:21 -06:00
6c95db8539 Fix channel ACTION routing after self-message handling
(cherry picked from commit bb3893d36c)
2026-09-15 09:12:16 -06:00
ThePeGaSuS
75286642df Fix CTCP ACTION not rerouting self-sent /me to correct PM window
Mirrors the PRIVMSG fix: replayed /me messages sent by our own nick
via WeeChat relay backlog were always passed with fromme=FALSE,
so they never got rerouted to the actual PM query window.

(cherry picked from commit c725adaa09)
2026-09-15 09:12:13 -06:00
ThePeGaSuS
8044b8562d Fix: private messages split into two windows over WeeChat's IRC relay
When you send a private message, ZoiteChat sometimes gets the same
message echoed back by the server so it can show it in the right
window. Whether it recognizes that echo depended on the server first
confirming a feature called "echo-message" during connection setup.

WeeChat's relay doesn't seem to confirm that feature the way other
servers (or ZNC) do, so ZoiteChat didn't recognize its own echoed
messages and treated them as brand new incoming messages from
yourself, opening a second, separate conversation window instead of
using the one you were already typing in.

This makes ZoiteChat recognize its own message by checking who sent
it, instead of only trusting that feature confirmation. That way,
sent and received messages always end up in the same conversation
window, regardless of how well the server/relay announces its
capabilities.

(cherry picked from commit 0ba523d071)
2026-09-15 09:12:09 -06:00
de6e16cbdf fix startup error on flatpak
(cherry picked from commit 36f0d7450c)
2026-09-15 09:12:02 -06:00
9 changed files with 55 additions and 31 deletions

View File

@@ -1 +1 @@
2.19.0
2.19.1

View File

@@ -2,6 +2,7 @@ appdir = join_paths(get_option('datadir'), 'applications')
metainfodir = join_paths(get_option('datadir'), 'metainfo')
mimedir = join_paths(get_option('datadir'), 'mime', 'packages')
desktop_utils = find_program('desktop-file-validate', required: false)
appstreamcli = find_program('appstreamcli', required: false)
if get_option('gtk-frontend')
if get_option('install-appdata')
@@ -13,7 +14,6 @@ if get_option('gtk-frontend')
install_dir: metainfodir
)
appstreamcli = find_program('appstreamcli', required: false)
if appstreamcli.found()
test('Validate net.zoite.Zoitechat.appdata.xml', appstreamcli,
args: ['validate', zoitechat_appdata]

View File

@@ -1,6 +1,6 @@
project('zoitechat', 'c',
version: run_command('cat', 'VERSION', check: true).stdout().strip(),
meson_version: '>= 0.55.0',
meson_version: '>= 0.59.0',
default_options: [
'c_std=c17',
'buildtype=debugoptimized',

View File

@@ -126,7 +126,21 @@ ctcp_handle (session *sess, char *to, char *nick, char *ip,
if (ctcp_check (sess, nick, word, word_eol, word[4] + ctcp_offset))
goto generic;
inbound_action (sess, to, nick, ip, msg + 7, FALSE, tags_data->identified, tags_data);
{
gboolean private_fromme = !serv->p_cmp (nick, serv->nick) && !is_channel (serv, to);
if (private_fromme)
{
session *target = find_dialog (serv, to);
if (target)
sess = target;
else if (serv->front_session)
sess = serv->front_session;
}
inbound_action (sess, to, nick, ip, msg + 7, private_fromme, tags_data->identified, tags_data);
}
return;
}

View File

@@ -13,9 +13,9 @@ dbus_includes = [
dbus_service_dir = join_paths(get_option('datadir'), 'dbus-1/services')
if get_option('dbus-service-use-appid')
dbus_service_name = 'io.github.Hexchat'
dbus_output_file = 'io.github.Hexchat.service'
dbus_cargs = '-DDBUS_SERVICE="io.github.Hexchat"'
dbus_service_name = 'net.zoite.Zoitechat'
dbus_output_file = 'net.zoite.Zoitechat.service'
dbus_cargs = '-DDBUS_SERVICE="net.zoite.Zoitechat"'
else
dbus_service_name = 'org.zoitechat.service'
dbus_output_file = 'org.zoitechat.service.service'

View File

@@ -858,8 +858,10 @@ path_depth_from_root (const char *base, const char *path)
static gint
theme_root_candidate_compare (gconstpointer a, gconstpointer b)
{
const ThemeRootCandidate *ca = a;
const ThemeRootCandidate *cb = b;
/* g_ptr_array_sort() passes pointers to the array slots, not the values
* stored in those slots. Dereference once before comparing candidates. */
const ThemeRootCandidate *ca = *(ThemeRootCandidate * const *) a;
const ThemeRootCandidate *cb = *(ThemeRootCandidate * const *) b;
if (ca->has_index_theme != cb->has_index_theme)
return ca->has_index_theme ? -1 : 1;
if (ca->depth != cb->depth)

View File

@@ -1368,7 +1368,7 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[],
{
if (ignore_check (word[1], IG_PRIV))
return;
if (serv->have_echo_message && !serv->p_cmp (nick, serv->nick))
if (!serv->p_cmp (nick, serv->nick))
{
session *target_sess = find_dialog (serv, to);

View File

@@ -463,8 +463,7 @@ doover:
while (list)
{
sess = list->data;
if (!sess->server->have_awaynotify)
sess->done_away_check = FALSE;
sess->done_away_check = FALSE;
list = list->next;
}
loop++;

View File

@@ -301,26 +301,35 @@ cv_tree_focus (chan *ch)
path = gtk_tree_model_get_path (model, &ch->iter);
if (path)
{
/* This full section does what
* gtk_tree_view_scroll_to_cell (tree, path, NULL, TRUE, 0.5, 0.5);
* does, except it only scrolls the window if the provided cell is
* not visible. Basic algorithm taken from gtktreeview.c */
/* obtain information to see if the cell is visible */
gtk_tree_view_get_background_area (tree, path, NULL, &cell_rect);
gtk_tree_view_get_visible_rect (tree, &vis_rect);
/* The cordinates aren't offset correctly */
gtk_tree_view_convert_widget_to_bin_window_coords ( tree, cell_rect.x, cell_rect.y, NULL, &cell_rect.y );
/* only need to scroll if out of bounds */
if (cell_rect.y < vis_rect.y ||
cell_rect.y + cell_rect.height > vis_rect.y + vis_rect.height)
if (!gtk_widget_get_realized (GTK_WIDGET (tree)))
{
dest_y = cell_rect.y - ((vis_rect.height - cell_rect.height) * 0.5);
if (dest_y < 0)
dest_y = 0;
gtk_tree_view_scroll_to_point (tree, -1, dest_y);
/* Layout changes can restore focus before the new tree is realized.
* Let GTK track the row and scroll once its geometry is available. */
gtk_tree_view_scroll_to_cell (tree, path, NULL, TRUE, 0.5, 0.5);
}
else
{
/* This full section does what
* gtk_tree_view_scroll_to_cell (tree, path, NULL, TRUE, 0.5, 0.5);
* does, except it only scrolls the window if the provided cell is
* not visible. Basic algorithm taken from gtktreeview.c */
/* obtain information to see if the cell is visible */
gtk_tree_view_get_background_area (tree, path, NULL, &cell_rect);
gtk_tree_view_get_visible_rect (tree, &vis_rect);
/* The cordinates aren't offset correctly */
gtk_tree_view_convert_widget_to_bin_window_coords ( tree, cell_rect.x, cell_rect.y, NULL, &cell_rect.y );
/* only need to scroll if out of bounds */
if (cell_rect.y < vis_rect.y ||
cell_rect.y + cell_rect.height > vis_rect.y + vis_rect.height)
{
dest_y = cell_rect.y - ((vis_rect.height - cell_rect.height) * 0.5);
if (dest_y < 0)
dest_y = 0;
gtk_tree_view_scroll_to_point (tree, -1, dest_y);
}
}
/* theft done, now make it focused like */
gtk_tree_view_set_cursor (tree, path, NULL, FALSE);