//! Modal methods for App //! //! Handles modal dialogs: Profile, Pinned Messages, Reactions, Delete Confirmation use crate::app::{App, ChatState}; use crate::tdlib::{MessageInfo, ProfileInfo, TdClientTrait}; use crate::types::MessageId; /// Modal dialog methods pub trait ModalMethods { // === Delete Confirmation === /// Check if delete confirmation modal is shown fn is_confirm_delete_shown(&self) -> bool; // === Pinned Messages === /// Check if in pinned messages mode fn is_pinned_mode(&self) -> bool; /// Enter pinned messages mode fn enter_pinned_mode(&mut self, messages: Vec); /// Exit pinned messages mode fn exit_pinned_mode(&mut self); /// Select previous pinned message (up = older) fn select_previous_pinned(&mut self); /// Select next pinned message (down = newer) fn select_next_pinned(&mut self); /// Get currently selected pinned message fn get_selected_pinned(&self) -> Option<&MessageInfo>; /// Get ID of selected pinned message for navigation fn get_selected_pinned_id(&self) -> Option; // === Profile === /// Check if in profile mode fn is_profile_mode(&self) -> bool; /// Enter profile mode fn enter_profile_mode(&mut self, info: ProfileInfo); /// Exit profile mode fn exit_profile_mode(&mut self); /// Select previous profile action fn select_previous_profile_action(&mut self); /// Select next profile action fn select_next_profile_action(&mut self, max_actions: usize); /// Show first leave group confirmation fn show_leave_group_confirmation(&mut self); /// Show second leave group confirmation fn show_leave_group_final_confirmation(&mut self); /// Cancel leave group confirmation fn cancel_leave_group(&mut self); /// Get current leave group confirmation step (0, 1, or 2) fn get_leave_group_confirmation_step(&self) -> u8; /// Get profile info fn get_profile_info(&self) -> Option<&ProfileInfo>; /// Get selected profile action index fn get_selected_profile_action(&self) -> Option; // === Reactions === /// Check if in reaction picker mode fn is_reaction_picker_mode(&self) -> bool; /// Enter reaction picker mode fn enter_reaction_picker_mode(&mut self, message_id: i64, available_reactions: Vec); /// Exit reaction picker mode fn exit_reaction_picker_mode(&mut self); /// Select previous reaction fn select_previous_reaction(&mut self); /// Select next reaction fn select_next_reaction(&mut self); /// Get currently selected reaction emoji fn get_selected_reaction(&self) -> Option<&String>; /// Get message ID for which reaction is being selected fn get_selected_message_for_reaction(&self) -> Option; } impl ModalMethods for App { fn is_confirm_delete_shown(&self) -> bool { self.chat_state.is_delete_confirmation() } fn is_pinned_mode(&self) -> bool { self.chat_state.is_pinned_mode() } fn enter_pinned_mode(&mut self, messages: Vec) { if !messages.is_empty() { self.chat_state = ChatState::PinnedMessages { messages, selected_index: 0, }; } } fn exit_pinned_mode(&mut self) { self.chat_state = ChatState::Normal; } fn select_previous_pinned(&mut self) { if let ChatState::PinnedMessages { selected_index, messages, } = &mut self.chat_state { if *selected_index + 1 < messages.len() { *selected_index += 1; } } } fn select_next_pinned(&mut self) { if let ChatState::PinnedMessages { selected_index, .. } = &mut self.chat_state { if *selected_index > 0 { *selected_index -= 1; } } } fn get_selected_pinned(&self) -> Option<&MessageInfo> { if let ChatState::PinnedMessages { messages, selected_index, } = &self.chat_state { messages.get(*selected_index) } else { None } } fn get_selected_pinned_id(&self) -> Option { self.get_selected_pinned().map(|m| m.id().as_i64()) } fn is_profile_mode(&self) -> bool { self.chat_state.is_profile() } fn enter_profile_mode(&mut self, info: ProfileInfo) { self.chat_state = ChatState::Profile { info, selected_action: 0, leave_group_confirmation_step: 0, }; } fn exit_profile_mode(&mut self) { self.chat_state = ChatState::Normal; } fn select_previous_profile_action(&mut self) { if let ChatState::Profile { selected_action, .. } = &mut self.chat_state { if *selected_action > 0 { *selected_action -= 1; } } } fn select_next_profile_action(&mut self, max_actions: usize) { if let ChatState::Profile { selected_action, .. } = &mut self.chat_state { if *selected_action < max_actions.saturating_sub(1) { *selected_action += 1; } } } fn show_leave_group_confirmation(&mut self) { if let ChatState::Profile { leave_group_confirmation_step, .. } = &mut self.chat_state { *leave_group_confirmation_step = 1; } } fn show_leave_group_final_confirmation(&mut self) { if let ChatState::Profile { leave_group_confirmation_step, .. } = &mut self.chat_state { *leave_group_confirmation_step = 2; } } fn cancel_leave_group(&mut self) { if let ChatState::Profile { leave_group_confirmation_step, .. } = &mut self.chat_state { *leave_group_confirmation_step = 0; } } fn get_leave_group_confirmation_step(&self) -> u8 { if let ChatState::Profile { leave_group_confirmation_step, .. } = &self.chat_state { *leave_group_confirmation_step } else { 0 } } fn get_profile_info(&self) -> Option<&ProfileInfo> { if let ChatState::Profile { info, .. } = &self.chat_state { Some(info) } else { None } } fn get_selected_profile_action(&self) -> Option { if let ChatState::Profile { selected_action, .. } = &self.chat_state { Some(*selected_action) } else { None } } fn is_reaction_picker_mode(&self) -> bool { self.chat_state.is_reaction_picker() } fn enter_reaction_picker_mode(&mut self, message_id: i64, available_reactions: Vec) { self.chat_state = ChatState::ReactionPicker { message_id: MessageId::new(message_id), available_reactions, selected_index: 0, }; } fn exit_reaction_picker_mode(&mut self) { self.chat_state = ChatState::Normal; } fn select_previous_reaction(&mut self) { if let ChatState::ReactionPicker { selected_index, .. } = &mut self.chat_state { if *selected_index > 0 { *selected_index -= 1; } } } fn select_next_reaction(&mut self) { if let ChatState::ReactionPicker { selected_index, available_reactions, .. } = &mut self.chat_state { if *selected_index + 1 < available_reactions.len() { *selected_index += 1; } } } fn get_selected_reaction(&self) -> Option<&String> { if let ChatState::ReactionPicker { available_reactions, selected_index, .. } = &self.chat_state { available_reactions.get(*selected_index) } else { None } } fn get_selected_message_for_reaction(&self) -> Option { self.chat_state.selected_message_id().map(|id| id.as_i64()) } }