NoteMAUI/NoteContent/EditorPage.xaml.cs

301 lines
10 KiB
C#

using CommunityToolkit.Maui.Views;
using NotesDataAnalyst.NoteContent;
using System.Text.RegularExpressions;
using System.Windows.Input;
namespace NotesDataAnalyst
{
public partial class EditorPage : ContentPage
{
//Âûçûâàåì ýìîäçè
public ICommand ShowEmojiPopupCommand { get; }
public ICommand ShowLinkInputCommand { get; }
public ICommand InsertHeaderCommand { get; }
public ICommand AddLinkCommand { get; }
private int listItemCounter = 1; // Ñ÷¸ò÷èê äëÿ íóìåðàöèè â ñïèñêå
private readonly Note _note;
private readonly FileSaver _fileSaver;
private readonly string _filePath;
public EditorPage(Note note = null)
{
InitializeComponent();
// Èíèöèàëèçàöèÿ êîìàíä
// Èíèöèàëèçàöèÿ êîìàíä
InsertHeaderCommand = new Command(InsertHeaderTag);
// InsertBulletCommand = new Command(InsertBulletPoint);
AddLinkCommand = new Command(AddLink);
// InsertNumberedListCommand = new Command(InsertNumberedListItem);
ShowLinkInputCommand = new Command(ShowLinkInputPopup);
//Èíèöèëèçèðóåì ýìîäçè
ShowEmojiPopupCommand = new Command(ShowEmojiSelectionPopup);
BindingContext = this; // Óñòàíàâëèâàåì êîíòåêñò ïðèâÿçêè íà òåêóùèé îáúåêò ñòðàíèöû
_note = note ?? new Note(); // Åñëè note íå ïåðåäàí, ñîçäà¸ì íîâóþ çàìåòêó
_filePath = string.Empty; // Ïóñòîé ïóòü óêàçûâàåò íà ñîçäàíèå íîâîé çàìåòêè
// Çàïîëíÿåì äàííûå, åñëè ýòî ñóùåñòâóþùàÿ çàìåòêà
if (_note != null)
{
categoryPicker.SelectedItem = _note.Category;
titleEditor.Text = _note.Title;
textEditor.Text = _note.Text;
if (!string.IsNullOrEmpty(_note.Image))
{
imageButton.Source = ImageSource.FromFile(_note.Image);
}
}
// Íàñòðàèâàåì âûáîð êàòåãîðèè è óñòàíîâêó ôîêóñà
CategoryManager.LoadCategories();
categoryPicker.ItemsSource = CategoryManager.Categories;
categoryPicker.SelectedItem = CategoryManager.ActiveCategory;
string basePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Notes");
_fileSaver = new FileSaver(basePath);
}
// Ðàáîòàåì ñ ýìîäçè
private async void ShowEmojiSelectionPopup()
{
var emojiPopup = new EmojiSelectionPopup();
// Îáðàáîò÷èê âûáîðà ñìàéëèêà
emojiPopup.EmojiSelected += emoji =>
{
InsertEmoji(emoji);
// Èñïîëüçóåì Dispatcher äëÿ áåçîïàñíîãî âûçîâà Close
Application.Current.Dispatcher.Dispatch(() =>
{
if (emojiPopup.Handler != null) // Ïðîâåðêà, ÷òî Popup åùå íå çàêðûò
{
emojiPopup.Close();
}
});
};
// Îòîáðàæàåì Popup
await Application.Current.MainPage.ShowPopupAsync(emojiPopup);
}
private void InsertEmoji(string emoji)
{
int cursorPosition = textEditor.CursorPosition;
textEditor.Text = textEditor.Text.Insert(cursorPosition, emoji);
textEditor.CursorPosition = cursorPosition + emoji.Length;
}
///////////////////////
///
/// <summary>
/// //////////////////////////////////////////////////////////////
/// </summary>
/// <param name="markdown"></param>
// Òýãè ìàðêäàóí
private void InsertHeaderTag()
{
if (textEditor == null)
{
Console.WriteLine("textEditor íå èíèöèàëèçèðîâàí.");
return;
}
// Ïðîâåðêà, åñëè òåêñò ïóñòîé
if (string.IsNullOrEmpty(textEditor.Text))
{
textEditor.Text = "# ";
textEditor.CursorPosition = textEditor.Text.Length;
return;
}
int cursorPosition = textEditor.CursorPosition;
string newText = cursorPosition == 0 || textEditor.Text[cursorPosition - 1] == '\n' ? "# " : "\n# ";
textEditor.Text = textEditor.Text.Insert(cursorPosition, newText);
textEditor.CursorPosition = cursorPosition + newText.Length;
}
private async void ShowLinkInputPopup()
{
var linkInputPopup = new LinkInputPopup();
// Ïîäïèñûâàåìñÿ íà ñîáûòèå, ÷òîáû ïîëó÷èòü ññûëêó è âñòàâèòü å¸ â òåêñò
linkInputPopup.LinkSubmitted += url =>
{
InsertLinkMarkdown(url);
};
// Îòêðûâàåì ìîäàëüíî
await Application.Current.MainPage.Navigation.PushModalAsync(linkInputPopup);
}
private void InsertLinkMarkdown(string url)
{
string markdownLink = $"![]({url})";
int cursorPosition = textEditor.CursorPosition;
textEditor.Text = textEditor.Text.Insert(cursorPosition, markdownLink);
textEditor.CursorPosition = cursorPosition + markdownLink.Length;
}
/* private void InsertBulletPoint()
{
if (textEditor == null)
{
Console.WriteLine("textEditor íå èíèöèàëèçèðîâàí.");
return;
}
if (string.IsNullOrEmpty(textEditor.Text))
{
textEditor.Text = "* ";
textEditor.CursorPosition = textEditor.Text.Length;
return;
}
int cursorPosition = textEditor.CursorPosition;
string bulletText = "* ";
textEditor.Text = textEditor.Text.Insert(cursorPosition, bulletText);
textEditor.CursorPosition = cursorPosition + bulletText.Length;
textEditor.Completed += (s, e) =>
{
if (!HasTwoEmptyLines(cursorPosition))
{
cursorPosition = textEditor.CursorPosition;
textEditor.Text = textEditor.Text.Insert(cursorPosition, bulletText);
textEditor.CursorPosition = cursorPosition + bulletText.Length;
}
};
}
private void InsertNumberedListItem()
{
int cursorPosition = textEditor.CursorPosition;
string listItemText = $"{listItemCounter}. ";
textEditor.Text = textEditor.Text.Insert(cursorPosition, listItemText);
textEditor.CursorPosition = cursorPosition + listItemText.Length;
// Îáíîâëÿåì íîìåð ñïèñêà ïðè ïåðåõîäå íà íîâóþ ñòðîêó
textEditor.Completed += (s, e) =>
{
if (!HasTwoEmptyLines(cursorPosition))
{
cursorPosition = textEditor.CursorPosition;
listItemCounter++;
listItemText = $"{listItemCounter}. ";
textEditor.Text = textEditor.Text.Insert(cursorPosition, listItemText);
textEditor.CursorPosition = cursorPosition + listItemText.Length;
}
else
{
listItemCounter = 1; // Ñáðîñ ñ÷¸ò÷èêà ïðè äâóõ ïóñòûõ ñòðîêàõ
}
};
}
// Ïðîâåðêà íà äâå ïóñòûå ñòðîêè ïîñëå ïîçèöèè êóðñîðà
private bool HasTwoEmptyLines(int position)
{
string textAfterCursor = textEditor.Text.Substring(position);
return Regex.IsMatch(textAfterCursor, @"\n\s*\n\s*\n");
}*/
////////////////////////////////////////////////////////////////////////////////////////////
private async void AddLink()
{
var popup = new NoteSelectionPopup();
popup.NoteSelected += OnNoteSelectedForLink;
await this.ShowPopupAsync(popup);
}
private void OnNoteSelectedForLink(Note selectedNote)
{
textEditor.Text = NoteLinkManager.InsertLink(textEditor.Text, selectedNote);
}
private async void OnImageTapped(object sender, EventArgs e)
{
try
{
var result = await FilePicker.PickAsync(new PickOptions
{
FileTypes = FilePickerFileType.Images,
PickerTitle = "Âûáåðèòå èçîáðàæåíèå"
});
if (result != null)
{
_note.Image = result.FullPath;
imageButton.Source = ImageSource.FromFile(result.FullPath);
}
}
catch (Exception ex)
{
await DisplayAlert("Îøèáêà", $"Íå óäàëîñü çàãðóçèòü èçîáðàæåíèå: {ex.Message}", "OK");
}
}
private async void SaveButton_Clicked(object sender, EventArgs e)
{
// Åñëè ó çàìåòêè íåò Id, ïðèñâàèâàåì íîâûé Id
if (string.IsNullOrEmpty(_note.Id))
{
_note.Id = Guid.NewGuid().ToString();
}
var note = new Note
{ Id = _note.Id,
Category = categoryPicker.SelectedItem as string,
Title = titleEditor.Text,
Image = _note.Image,
Text = textEditor.Text,
FilePath = _filePath
};
// Ïðîâåðêà çàãîëîâêà
if (string.IsNullOrEmpty(note.Title))
{
// Ïîëó÷àåì ïåðâûå 4 ñëîâà èç òåêñòà
var words = note.Text.Split(' ', StringSplitOptions.RemoveEmptyEntries);
note.Title = string.Join(" ", words.Take(4));
}
//Çàïèñü â ÁÄ ïîêà îòêëþ÷åíà
await Task.Run(() => App.Database.SaveNote(note));
// Îòïðàâëÿåì ñîîáùåíèå äëÿ îáíîâëåíèÿ ñïèñêà çàìåòîê íà ãëàâíîé ñòðàíèöå
MessagingCenter.Send(this, "NoteSaved", _note);
await DisplayAlert("Success", "Note saved successfully.", "OK");
await Navigation.PushAsync(new MainPage());
}
}
}