@@ -149,4 +149,113 @@ namespace Dc {
149149 return dt. format (" %d /%m /%y " );
150150 }
151151 }
152+
153+ public class ChatContextMenu : Object {
154+
155+ private unowned Window window;
156+ private unowned RpcClient rpc;
157+ private unowned GLib . ListStore chat_store;
158+
159+ public ChatContextMenu (Window window , RpcClient rpc ,
160+ GLib .ListStore chat_store ) {
161+ this . window = window;
162+ this . rpc = rpc;
163+ this . chat_store = chat_store;
164+ }
165+
166+ public void show (int chat_id , double x , double y , Gtk .Widget parent ) {
167+ bool is_pinned = false ;
168+ var entry = find_chat_entry (chat_store, chat_id);
169+ if (entry != null ) is_pinned = entry. is_pinned;
170+
171+ var menu = new GLib .Menu ();
172+ menu. append (is_pinned ? " Unpin" : " Pin" , " win.chat-pin" );
173+ menu. append (" Chat Info" , " win.chat-info" );
174+ menu. append (" Delete for Me" , " win.chat-delete" );
175+
176+ var pin_action = new SimpleAction (" chat-pin" , null );
177+ pin_action. activate. connect (() = > {
178+ toggle_pin. begin (chat_id, is_pinned);
179+ });
180+ var info_action = new SimpleAction (" chat-info" , null );
181+ info_action. activate. connect (() = > {
182+ show_info. begin (chat_id);
183+ });
184+ var delete_action = new SimpleAction (" chat-delete" , null );
185+ delete_action. activate. connect (() = > {
186+ confirm_delete. begin (chat_id);
187+ });
188+
189+ window. add_action (pin_action);
190+ window. add_action (info_action);
191+ window. add_action (delete_action);
192+
193+ var popover = new Gtk .PopoverMenu .from_model (menu);
194+ popover. set_parent (parent);
195+ popover. set_pointing_to ({ (int ) x, (int ) y, 1 , 1 });
196+ popover. popup ();
197+ }
198+
199+ private async void toggle_pin (int chat_id , bool currently_pinned ) {
200+ try {
201+ string visibility = currently_pinned ? " Normal" : " Pinned" ;
202+ yield rpc. set_chat_visibility (rpc. account_id, chat_id, visibility);
203+ yield window. load_chats ();
204+ } catch (Error e) {
205+ window. show_toast (" Failed to update pin: " + e. message);
206+ }
207+ }
208+
209+ private async void show_info (int chat_id ) {
210+ var dialog = new ChatInfoDialog (rpc, rpc. account_id, chat_id);
211+
212+ dialog. chat_deleted. connect ((cid) = > {
213+ window. show_toast (" Chat deleted" );
214+ if (window. current_chat_id == cid)
215+ window. clear_chat_view ();
216+ window. request_reload_chats ();
217+ });
218+
219+ dialog. chat_changed. connect (() = > {
220+ window. request_reload_chats ();
221+ if (window. current_chat_id == chat_id)
222+ window. request_messages_reload ();
223+ });
224+
225+ dialog. present (window);
226+ }
227+
228+ private async void confirm_delete (int chat_id ) {
229+ string chat_name = " this chat" ;
230+ var entry = find_chat_entry (chat_store, chat_id);
231+ if (entry != null ) chat_name = entry. name;
232+
233+ var dialog = new Adw .AlertDialog (
234+ " Delete for Me" ,
235+ " Remove \"%s\" from your chat list? You may still receive messages if you are a group member." . printf (chat_name)
236+ );
237+ dialog. add_response (" cancel" , " Cancel" );
238+ dialog. add_response (" delete" , " Delete for Me" );
239+ dialog. set_response_appearance (" delete" , Adw . ResponseAppearance . DESTRUCTIVE );
240+ dialog. default_response = " cancel" ;
241+
242+ dialog. response. connect ((resp) = > {
243+ if (resp == " delete" ) do_delete. begin (chat_id);
244+ });
245+
246+ dialog. present (window);
247+ }
248+
249+ private async void do_delete (int chat_id ) {
250+ try {
251+ yield rpc. delete_chat (rpc. account_id, chat_id);
252+ window. show_toast (" Chat deleted" );
253+ if (window. current_chat_id == chat_id)
254+ window. clear_chat_view ();
255+ yield window. load_chats ();
256+ } catch (Error e) {
257+ window. show_toast (" Delete failed: " + e. message);
258+ }
259+ }
260+ }
152261}
0 commit comments