Добавьте файлы проекта.
14
App.xaml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version = "1.0" encoding = "UTF-8" ?>
|
||||
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:local="clr-namespace:NotesDataAnalyst.NoteContent"
|
||||
x:Class="NotesDataAnalyst.App">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="/Resources/Styles/Colors.xaml" />
|
||||
<ResourceDictionary Source="/Resources/Styles/Styles.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
37
App.xaml.cs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
|
||||
|
||||
using NotesDataAnalyst.NoteContent;
|
||||
|
||||
namespace NotesDataAnalyst
|
||||
{
|
||||
public partial class App : Application
|
||||
{
|
||||
public static List<Note> AllNotes { get; set; } = new List<Note>();
|
||||
|
||||
public static DatabaseContext Database { get; private set; }
|
||||
|
||||
public App()
|
||||
{
|
||||
InitializeComponent();
|
||||
string dbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "notes.db");
|
||||
Database = new DatabaseContext(dbPath);
|
||||
MainPage = new AppShell();
|
||||
}
|
||||
|
||||
// Метод для добавления или сохранения заметки
|
||||
public static void SaveNote(Note note)
|
||||
{
|
||||
var existingNote = AllNotes.FirstOrDefault(n => n.Id == note.Id);
|
||||
if (existingNote == null)
|
||||
{
|
||||
AllNotes.Add(note);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Обновляем существующую заметку
|
||||
existingNote.Title = note.Title;
|
||||
existingNote.Text = note.Text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
AppShell.xaml
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<Shell
|
||||
x:Class="NotesDataAnalyst.AppShell"
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:local="clr-namespace:NotesDataAnalyst"
|
||||
Shell.FlyoutBehavior="Flyout"
|
||||
Shell.NavBarIsVisible="True"
|
||||
Title="NotesDataAnalyst">
|
||||
|
||||
<!-- Главная страница приложения -->
|
||||
<FlyoutItem Title="Главная" Icon="add.png">
|
||||
<ShellContent ContentTemplate="{DataTemplate local:GraphPage}" />
|
||||
</FlyoutItem>
|
||||
|
||||
<!-- Выпадающий список категорий -->
|
||||
<MenuItem Text="Категории" Clicked="OnCategoriesMenuClicked" />
|
||||
</Shell>
|
||||
74
AppShell.xaml.cs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
namespace NotesDataAnalyst
|
||||
{
|
||||
public partial class AppShell : Shell
|
||||
{
|
||||
public AppShell()
|
||||
{
|
||||
InitializeComponent();
|
||||
CategoryManager.LoadCategories(); // Загружаем категории при запуске
|
||||
// Регистрация маршрута для MainPage
|
||||
Routing.RegisterRoute("MainPage", typeof(MainPage));
|
||||
}
|
||||
|
||||
private async void OnCategoriesMenuClicked(object sender, EventArgs e)
|
||||
{
|
||||
// Открываем всплывающее окно с возможностью управления категориями
|
||||
string action = await DisplayActionSheet("Управление категориями", "Отмена", null,
|
||||
"Выбрать категорию", "Добавить категорию", "Удалить категорию");
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case "Выбрать категорию":
|
||||
await SelectCategory();
|
||||
break;
|
||||
case "Добавить категорию":
|
||||
await AddCategory();
|
||||
break;
|
||||
case "Удалить категорию":
|
||||
await DeleteCategory();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SelectCategory()
|
||||
{
|
||||
// Всплывающее окно для выбора категории
|
||||
string selectedCategory = await DisplayActionSheet("Выберите категорию", "Отмена", null, CategoryManager.Categories.ToArray());
|
||||
if (!string.IsNullOrEmpty(selectedCategory) && selectedCategory != "Отмена")
|
||||
{
|
||||
// Устанавливаем выбранную категорию
|
||||
CategoryManager.ActiveCategory = selectedCategory;
|
||||
// Переход к MainPage относительно текущего стека, без абсолютного маршрута
|
||||
await Shell.Current.GoToAsync("MainPage");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task AddCategory()
|
||||
{
|
||||
// Всплывающее окно для ввода названия новой категории
|
||||
string newCategory = await DisplayPromptAsync("Новая категория", "Введите название категории:");
|
||||
if (!string.IsNullOrWhiteSpace(newCategory) && !CategoryManager.Categories.Contains(newCategory))
|
||||
{
|
||||
CategoryManager.AddCategory(newCategory);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeleteCategory()
|
||||
{
|
||||
// Всплывающее окно для выбора категории для удаления
|
||||
string categoryToDelete = await DisplayActionSheet("Удалить категорию", "Отмена", null, CategoryManager.Categories.ToArray());
|
||||
if (!string.IsNullOrEmpty(categoryToDelete) && categoryToDelete != "Отмена")
|
||||
{
|
||||
// Удаляем категорию
|
||||
CategoryManager.Categories.Remove(categoryToDelete);
|
||||
|
||||
// Сброс активной категории, если она была удалена
|
||||
if (CategoryManager.ActiveCategory == categoryToDelete)
|
||||
{
|
||||
CategoryManager.ActiveCategory = "Все категории";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
80
GraphDrawable.cs
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
using Microsoft.Maui.Graphics;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NotesDataAnalyst
|
||||
{
|
||||
public class GraphDrawable : IDrawable
|
||||
{
|
||||
private readonly List<GraphNode> _nodes;
|
||||
private readonly List<GraphConnection> _connections;
|
||||
|
||||
public GraphDrawable(List<GraphNode> nodes, List<GraphConnection> connections)
|
||||
{
|
||||
_nodes = nodes;
|
||||
_connections = connections;
|
||||
}
|
||||
|
||||
private void DrawConnection(ICanvas canvas, GraphConnection connection)
|
||||
{
|
||||
var startX = connection.FromNode.Position.X + connection.FromNode.Size.Width / 2;
|
||||
var startY = connection.FromNode.Position.Y + connection.FromNode.Size.Height / 2;
|
||||
var endX = connection.ToNode.Position.X + connection.ToNode.Size.Width / 2;
|
||||
var endY = connection.ToNode.Position.Y + connection.ToNode.Size.Height / 2;
|
||||
|
||||
canvas.StrokeColor = Colors.Gray;
|
||||
canvas.StrokeSize = 2;
|
||||
canvas.DrawLine((float)startX, (float)startY, (float)endX, (float)endY);
|
||||
}
|
||||
|
||||
|
||||
private void DrawNode(ICanvas canvas, GraphNode node)
|
||||
{
|
||||
canvas.FillColor = node.BackgroundColor;
|
||||
canvas.FillRectangle((float)node.Position.X, (float)node.Position.Y, (float)node.Size.Width, (float)node.Size.Height);
|
||||
|
||||
canvas.FontColor = Colors.Black;
|
||||
canvas.DrawString(node.Text, (float)node.Position.X + 10, (float)node.Position.Y + 20, HorizontalAlignment.Left);
|
||||
}
|
||||
|
||||
public void Draw(ICanvas canvas, RectF dirtyRect)
|
||||
{
|
||||
canvas.StrokeColor = Colors.Black;
|
||||
canvas.StrokeSize = 2;
|
||||
|
||||
// Отрисовка связей
|
||||
foreach (var connection in _connections)
|
||||
{
|
||||
canvas.DrawLine(
|
||||
(float)connection.FromNode.Position.X, (float)connection.FromNode.Position.Y,
|
||||
(float)connection.ToNode.Position.X, (float)connection.ToNode.Position.Y);
|
||||
}
|
||||
|
||||
// Отрисовка узлов
|
||||
foreach (var node in _nodes)
|
||||
{
|
||||
// Заливка фона узла
|
||||
canvas.FillColor = node.BackgroundColor;
|
||||
canvas.FillRectangle((float)node.Position.X, (float)node.Position.Y, (float)node.Size.Width, (float)node.Size.Height);
|
||||
|
||||
// Отрисовка текста
|
||||
canvas.FontColor = Colors.Black;
|
||||
canvas.DrawString(node.Text, (float)node.Position.X + 5, (float)node.Position.Y + 5, HorizontalAlignment.Left);
|
||||
|
||||
// Если нода выбрана, рисуем пунктирную обводку и "ручку" для изменения размера
|
||||
if (node.IsActive)
|
||||
{
|
||||
canvas.StrokeColor = Colors.Blue;
|
||||
canvas.StrokeDashPattern = new float[] { 4, 2 };
|
||||
canvas.DrawRectangle((float)node.Position.X, (float)node.Position.Y, (float)node.Size.Width, (float)node.Size.Height);
|
||||
|
||||
// Ручка для изменения размера
|
||||
canvas.FillColor = Colors.Gray;
|
||||
canvas.FillRectangle(
|
||||
(float)(node.Position.X + node.Size.Width - 10),
|
||||
(float)(node.Position.Y + node.Size.Height - 10),
|
||||
10, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
25
GraphNode.cs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NotesDataAnalyst
|
||||
{
|
||||
public class GraphNode
|
||||
{
|
||||
public bool IsActive { get; set; }
|
||||
public string Id { get; } = Guid.NewGuid().ToString(); // Уникальный идентификатор
|
||||
public string Text { get; set; }
|
||||
public Color BackgroundColor { get; set; } = Colors.LightBlue;
|
||||
public Point Position { get; set; } // Позиция узла
|
||||
public Size Size { get; set; } = new Size(100, 50); // Размер узла
|
||||
public List<GraphNode> Children { get; } = new List<GraphNode>(); // Список дочерних узлов
|
||||
}
|
||||
|
||||
public class GraphConnection
|
||||
{
|
||||
public GraphNode FromNode { get; set; } // Узел начала связи
|
||||
public GraphNode ToNode { get; set; } // Узел конца связи
|
||||
}
|
||||
}
|
||||
18
GraphPage.xaml
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
|
||||
x:Class="NotesDataAnalyst.GraphPage"
|
||||
Title="GraphPage">
|
||||
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem Text="Add Node" Clicked="OnAddNodeClicked"/>
|
||||
<ToolbarItem Text="Добавить дочернюю" Clicked="OnChildClicked"/>
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
<ContentPage.Content>
|
||||
<GraphicsView x:Name="canvasView"
|
||||
HeightRequest="800"
|
||||
WidthRequest="800" />
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
||||
310
GraphPage.xaml.cs
Normal file
|
|
@ -0,0 +1,310 @@
|
|||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
namespace NotesDataAnalyst
|
||||
{
|
||||
|
||||
public partial class GraphPage : ContentPage
|
||||
{
|
||||
private readonly Entry _textEditor; // Ïîëå äëÿ ââîäà òåêñòà
|
||||
private PointF _initialNodePosition; // Õðàíèò íà÷àëüíóþ ïîçèöèþ íîäû
|
||||
private PointF _initialTouchPosition; // Õðàíèò íà÷àëüíóþ ïîçèöèþ êàñàíèÿ
|
||||
private SizeF _initialNodeSize; // Õðàíèò íà÷àëüíûé ðàçìåð íîäû
|
||||
|
||||
private readonly List<GraphNode> _nodes = new();
|
||||
private readonly List<GraphConnection> _connections = new();
|
||||
private GraphNode _selectedNode;
|
||||
private bool _isResizing = false;
|
||||
|
||||
public GraphPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// Ñîçäàåì ñêðûòîå ïîëå äëÿ ðåäàêòèðîâàíèÿ òåêñòà
|
||||
_textEditor = new Entry
|
||||
{
|
||||
IsVisible = false,
|
||||
BackgroundColor = Colors.Transparent,
|
||||
FontSize = 18,
|
||||
TextColor = Colors.Black
|
||||
};
|
||||
_textEditor.Completed += OnTextEditorCompleted; // Ñîõðàíÿåì òåêñò ïðè çàâåðøåíèè ââîäà
|
||||
this.Add(_textEditor);
|
||||
|
||||
// Íàñòðàèâàåì Drawable äëÿ îòðèñîâêè óçëîâ è ñâÿçåé
|
||||
var graphDrawable = new GraphDrawable(_nodes, _connections);
|
||||
canvasView.Drawable = graphDrawable;
|
||||
|
||||
// Äîáàâëÿåì æåñòû
|
||||
var panGesture = new PanGestureRecognizer();
|
||||
panGesture.PanUpdated += OnPanUpdated;
|
||||
canvasView.GestureRecognizers.Add(panGesture);
|
||||
|
||||
var tapGesture = new TapGestureRecognizer();
|
||||
tapGesture.Tapped += OnCanvasTapped;
|
||||
canvasView.GestureRecognizers.Add(tapGesture);
|
||||
}
|
||||
|
||||
private void OnNodeTapped(object sender, TappedEventArgs e)
|
||||
{
|
||||
var node = _selectedNode;
|
||||
|
||||
var tapPosition = e.GetPosition((View)sender);
|
||||
if (tapPosition.HasValue)
|
||||
{
|
||||
var touchPoint = new PointF((float)tapPosition.Value.X, (float)tapPosition.Value.Y);
|
||||
_selectedNode = _nodes.FirstOrDefault(node => IsPointInsideNode(touchPoint, node));
|
||||
|
||||
if (_selectedNode != null)
|
||||
{
|
||||
// Ïîçèöèîíèðóåì è ïîêàçûâàåì òåêñòîâîå ïîëå
|
||||
_textEditor.Text = _selectedNode.Text;
|
||||
_textEditor.IsVisible = true;
|
||||
_textEditor.Focus();
|
||||
AbsoluteLayout.SetLayoutBounds(_textEditor, new Rect(_selectedNode.Position.X + 5, _selectedNode.Position.Y + 5, _selectedNode.Size.Width - 10, 30));
|
||||
}
|
||||
}
|
||||
|
||||
Debug.WriteLine("Íàæàòà íîäà - {node}");
|
||||
}
|
||||
|
||||
private void OnTextEditorCompleted(object sender, EventArgs e)
|
||||
{
|
||||
// Ñîõðàíÿåì òåêñò â íîäó
|
||||
if (_selectedNode != null)
|
||||
{
|
||||
_selectedNode.Text = _textEditor.Text;
|
||||
_textEditor.IsVisible = false;
|
||||
canvasView.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void OnChildClicked(object sender, EventArgs e)
|
||||
{
|
||||
if (_selectedNode != null)
|
||||
{
|
||||
var child = new GraphNode
|
||||
{
|
||||
Text = "Child Node",
|
||||
Position = new Point(_selectedNode.Position.X + 5, _selectedNode.Position.Y + 5),
|
||||
Size = _selectedNode.Size,
|
||||
BackgroundColor = Colors.Gray,
|
||||
};
|
||||
_nodes.Add(child);
|
||||
_connections.Add(new GraphConnection { FromNode = _selectedNode, ToNode = child });
|
||||
canvasView.Invalidate();
|
||||
|
||||
}
|
||||
else { Debug.WriteLine("Ñíà÷àëà âûáèðèòå íîäó"); }
|
||||
}
|
||||
|
||||
private async void OnAddNodeClicked(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
var newNode = new GraphNode
|
||||
{
|
||||
Text = "Íîâàÿ íîäà",
|
||||
Position = new Point(300, 200),
|
||||
Size = new Size(200, 200),
|
||||
|
||||
};
|
||||
|
||||
_nodes.Add(newNode);
|
||||
canvasView.Invalidate();
|
||||
}
|
||||
|
||||
// Îáðàáîò÷èê äëÿ âûáîðà óçëà
|
||||
// Îáðàáîò÷èê äëÿ âûáîðà óçëà
|
||||
private void OnCanvasTapped(object sender, TappedEventArgs e)
|
||||
{
|
||||
var tapPosition = e.GetPosition((View)sender);
|
||||
_selectedNode = null;
|
||||
|
||||
if (tapPosition.HasValue)
|
||||
{
|
||||
var touchPoint = new PointF((float)tapPosition.Value.X, (float)tapPosition.Value.Y);
|
||||
_selectedNode = _nodes.FirstOrDefault(node => IsPointInsideNode(touchPoint, node));
|
||||
|
||||
// Ñáðîñ àêòèâíîñòè äëÿ âñåõ óçëîâ, êðîìå âûáðàííîãî
|
||||
foreach (var node in _nodes)
|
||||
node.IsActive = node == _selectedNode;
|
||||
|
||||
// Îáíîâëÿåì ýêðàí ïîñëå èçìåíåíèÿ ñîñòîÿíèÿ óçëîâ
|
||||
canvasView.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
|
||||
{
|
||||
if (_selectedNode == null) return;
|
||||
|
||||
if (e.StatusType == GestureStatus.Started)
|
||||
{
|
||||
// Ñîõðàíÿåì íà÷àëüíóþ ïîçèöèþ íîäû è ðàçìåð
|
||||
_initialNodePosition = _selectedNode.Position;
|
||||
_initialTouchPosition = new PointF((float)e.TotalX, (float)e.TotalY);
|
||||
_initialNodeSize = _selectedNode.Size; // Ñîõðàíÿåì íà÷àëüíûé ðàçìåð
|
||||
|
||||
// Ïðîâåðÿåì, íàõîäèìñÿ ëè ìû íà ðó÷êå èçìåíåíèÿ ðàçìåðà
|
||||
_isResizing = IsOnRightResizeHandle(_selectedNode, _initialTouchPosition) ||
|
||||
IsOnLeftResizeHandle(_selectedNode, _initialTouchPosition) ||
|
||||
IsOnTopResizeHandle(_selectedNode, _initialTouchPosition) ||
|
||||
IsOnBottomResizeHandle(_selectedNode, _initialTouchPosition);
|
||||
|
||||
}
|
||||
else if (e.StatusType == GestureStatus.Running)
|
||||
{
|
||||
// Âû÷èñëÿåì ñìåùåíèå îò íà÷àëüíîé ïîçèöèè êàñàíèÿ
|
||||
var deltaX = (float)e.TotalX - _initialTouchPosition.X;
|
||||
var deltaY = (float)e.TotalY - _initialTouchPosition.Y;
|
||||
|
||||
if (_isResizing)
|
||||
{
|
||||
ResizeNode(_selectedNode, deltaX, deltaY);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ïåðåìåùåíèå
|
||||
_selectedNode.Position = new PointF(
|
||||
_initialNodePosition.X + deltaX,
|
||||
_initialNodePosition.Y + deltaY
|
||||
);
|
||||
}
|
||||
|
||||
canvasView.Invalidate();
|
||||
}
|
||||
else if (e.StatusType == GestureStatus.Completed)
|
||||
{
|
||||
_isResizing = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Èçìåíåíèå ðàçìåðà óçëà
|
||||
private void ResizeNode(GraphNode node, double deltaX, double deltaY)
|
||||
{
|
||||
const float minSize = 50f; // Óáèðàåì "f" äëÿ double
|
||||
|
||||
// Óâåëè÷èâàåì èëè óìåíüøàåì ðàçìåð â çàâèñèìîñòè îò íàïðàâëåíèÿ
|
||||
if (_isResizing)
|
||||
{
|
||||
// Åñëè ìû òÿíåì ïðàâóþ "ðó÷êó", óâåëè÷èâàåì øèðèíó
|
||||
if (IsOnRightResizeHandle(node, _initialTouchPosition))
|
||||
{
|
||||
_selectedNode.Size = new Size(
|
||||
Math.Max(minSize, node.Size.Width + deltaX), // double
|
||||
_selectedNode.Size.Height // double
|
||||
);
|
||||
}
|
||||
// Åñëè ìû òÿíåì ëåâóþ "ðó÷êó", óìåíüøàåì øèðèíó
|
||||
else if (IsOnLeftResizeHandle(node, _initialTouchPosition))
|
||||
{
|
||||
_selectedNode.Size = new Size(
|
||||
Math.Max(minSize, _selectedNode.Size.Width - deltaX), // double
|
||||
_selectedNode.Size.Height // double
|
||||
);
|
||||
|
||||
// Ïåðåìåùàåì íîäó âëåâî, ÷òîáû ñîõðàíèòü åå ïîçèöèþ
|
||||
_selectedNode.Position = new Point(_selectedNode.Position.X + deltaX, _selectedNode.Position.Y); // double
|
||||
}
|
||||
// Åñëè ìû òÿíåì âåðõíþþ "ðó÷êó", óìåíüøàåì âûñîòó
|
||||
else if (IsOnTopResizeHandle(node, _initialTouchPosition))
|
||||
{
|
||||
_selectedNode.Size = new Size(
|
||||
_selectedNode.Size.Width, // double
|
||||
Math.Max(minSize, _selectedNode.Size.Height - deltaY) // double
|
||||
);
|
||||
|
||||
// Ïåðåìåùàåì íîäó ââåðõ, ÷òîáû ñîõðàíèòü åå ïîçèöèþ
|
||||
_selectedNode.Position = new Point(_selectedNode.Position.X, _selectedNode.Position.Y + deltaY); // double
|
||||
}
|
||||
// Åñëè ìû òÿíåì íèæíþþ "ðó÷êó", óâåëè÷èâàåì âûñîòó
|
||||
else if (IsOnBottomResizeHandle(node, _initialTouchPosition))
|
||||
{
|
||||
_selectedNode.Size = new Size(
|
||||
_selectedNode.Size.Width, // double
|
||||
Math.Max(minSize, _selectedNode.Size.Height + deltaY) // double
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private bool IsOnRightResizeHandle(GraphNode node, PointF point)
|
||||
{
|
||||
const float handleSize = 400;
|
||||
return Math.Abs(point.X - (node.Position.X + node.Size.Width)) <= handleSize;
|
||||
}
|
||||
|
||||
private bool IsOnLeftResizeHandle(GraphNode node, PointF point)
|
||||
{
|
||||
const float handleSize = 400;
|
||||
return Math.Abs(point.X - node.Position.X) <= handleSize;
|
||||
}
|
||||
|
||||
private bool IsOnTopResizeHandle(GraphNode node, PointF point)
|
||||
{
|
||||
const float handleSize = 400;
|
||||
return Math.Abs(point.Y - node.Position.Y) <= handleSize;
|
||||
}
|
||||
|
||||
private bool IsOnBottomResizeHandle(GraphNode node, PointF point)
|
||||
{
|
||||
const float handleSize = 400;
|
||||
return Math.Abs(point.Y - (node.Position.Y + node.Size.Height)) <= handleSize;
|
||||
}
|
||||
|
||||
|
||||
// Ìåòîä äëÿ ïðîâåðêè, íàõîäèòñÿ ëè òî÷êà âíóòðè óçëà
|
||||
private bool IsPointInsideNode(PointF point, GraphNode node)
|
||||
{
|
||||
return point.X >= node.Position.X &&
|
||||
point.X <= node.Position.X + node.Size.Width &&
|
||||
point.Y >= node.Position.Y &&
|
||||
point.Y <= node.Position.Y + node.Size.Height;
|
||||
}
|
||||
|
||||
|
||||
// Ïðîâåðêà, íàõîäèòñÿ ëè òî÷êà íà "ðó÷êå" èçìåíåíèÿ ðàçìåðà
|
||||
private bool IsOnResizeHandle(GraphNode node, PointF point)
|
||||
{
|
||||
const float handleSize = 200f; // Ðàçìåð ðó÷êè èçìåíåíèÿ ðàçìåðà
|
||||
|
||||
// Îïðåäåëÿåì ïðÿìîóãîëüíèêè äëÿ êàæäîé ðó÷êè
|
||||
var rightHandleRect = new RectF(
|
||||
(float)(node.Position.X + node.Size.Width - handleSize),
|
||||
(float)(node.Position.Y + node.Size.Height - handleSize),
|
||||
handleSize, handleSize);
|
||||
|
||||
var leftHandleRect = new RectF(
|
||||
(float)(node.Position.X),
|
||||
(float)(node.Position.Y + node.Size.Height - handleSize),
|
||||
handleSize, handleSize);
|
||||
|
||||
var topHandleRect = new RectF(
|
||||
(float)(node.Position.X + (node.Size.Width / 2) - (handleSize / 2)),
|
||||
(float)(node.Position.Y),
|
||||
handleSize, handleSize);
|
||||
|
||||
var bottomHandleRect = new RectF(
|
||||
(float)(node.Position.X + (node.Size.Width / 2) - (handleSize / 2)),
|
||||
(float)(node.Position.Y + node.Size.Height - handleSize),
|
||||
handleSize, handleSize);
|
||||
|
||||
// Ïðîâåðÿåì, íàõîäèòñÿ ëè êóðñîð íà îäíîé èç ðó÷åê
|
||||
return rightHandleRect.Contains(point) ||
|
||||
leftHandleRect.Contains(point) ||
|
||||
topHandleRect.Contains(point) ||
|
||||
bottomHandleRect.Contains(point);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
22
MauiProgram.cs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
using Microsoft.Extensions.Logging;
|
||||
using CommunityToolkit.Maui;
|
||||
|
||||
namespace NotesDataAnalyst
|
||||
{
|
||||
public static class MauiProgram
|
||||
{
|
||||
public static MauiApp CreateMauiApp()
|
||||
{
|
||||
var builder = MauiApp.CreateBuilder();
|
||||
builder
|
||||
.UseMauiApp<App>()
|
||||
.UseMauiCommunityToolkit() // Подключение CommunityToolkit.Maui
|
||||
.ConfigureFonts(fonts =>
|
||||
{
|
||||
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
|
||||
});
|
||||
|
||||
return builder.Build();
|
||||
}
|
||||
}
|
||||
}
|
||||
48
NoteContent/CategoryManager.cs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
using System.Collections.ObjectModel;
|
||||
using Microsoft.Maui.Storage;
|
||||
|
||||
public static class CategoryManager
|
||||
{
|
||||
public static ObservableCollection<string> Categories { get; private set; } = new ObservableCollection<string>();
|
||||
|
||||
private const string ActiveCategoryKey = "ActiveCategory";
|
||||
|
||||
public static string ActiveCategory
|
||||
{
|
||||
get => Preferences.Get(ActiveCategoryKey, Categories.FirstOrDefault() ?? ""); // Проверка на null
|
||||
set
|
||||
{
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
Preferences.Set(ActiveCategoryKey, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void LoadCategories()
|
||||
{
|
||||
if (Categories.Count == 0) // Проверка, чтобы не загружать повторно
|
||||
{
|
||||
Categories.Add("Личное");
|
||||
Categories.Add("Работа");
|
||||
Categories.Add("Дом");
|
||||
|
||||
// Устанавливаем первую категорию как активную, если она не задана
|
||||
if (string.IsNullOrEmpty(ActiveCategory))
|
||||
{
|
||||
ActiveCategory = Categories.First();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddCategory(string category)
|
||||
{
|
||||
if (!Categories.Contains(category))
|
||||
{
|
||||
Categories.Add(category);
|
||||
ActiveCategory = category; // Сразу делаем новую категорию активной
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
126
NoteContent/DatabaseContext.cs
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using System.Collections.ObjectModel;
|
||||
namespace NotesDataAnalyst.NoteContent
|
||||
{
|
||||
|
||||
|
||||
public class DatabaseContext
|
||||
{
|
||||
private readonly string _connectionString;
|
||||
|
||||
public DatabaseContext(string dbPath)
|
||||
{
|
||||
_connectionString = $"Data Source={dbPath}";
|
||||
InitializeDatabase();
|
||||
}
|
||||
|
||||
private void InitializeDatabase()
|
||||
{
|
||||
using (var connection = new SqliteConnection(_connectionString))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText =
|
||||
@"
|
||||
CREATE TABLE IF NOT EXISTS Notes (
|
||||
Id TEXT PRIMARY KEY,
|
||||
Category TEXT,
|
||||
Title TEXT,
|
||||
Image TEXT,
|
||||
Text TEXT,
|
||||
DateCreated TEXT
|
||||
);
|
||||
";
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<Note> GetAllNotes()
|
||||
{
|
||||
var notes = new ObservableCollection<Note>();
|
||||
|
||||
using (var connection = new SqliteConnection(_connectionString))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT * FROM Notes";
|
||||
using (var reader = command.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
var note = new Note
|
||||
{
|
||||
Id = reader.GetString(0),
|
||||
Category = reader.GetString(1),
|
||||
Title = reader.GetString(2),
|
||||
Image = reader.GetString(3),
|
||||
Text = reader.GetString(4), // Загружаем текст из БД
|
||||
DateCreated = DateTime.TryParse(reader.GetString(5), out var date) ? date : DateTime.UtcNow
|
||||
};
|
||||
|
||||
notes.Add(note);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return notes;
|
||||
}
|
||||
|
||||
public void SaveNote(Note note)
|
||||
{
|
||||
using (var connection = new SqliteConnection(_connectionString))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText =
|
||||
@"
|
||||
INSERT OR REPLACE INTO Notes (Id, Category, Title, Image, Text, DateCreated)
|
||||
VALUES ($id, $category, $title, $image, $text, $dateCreated)
|
||||
";
|
||||
command.Parameters.AddWithValue("$id", note.Id);
|
||||
command.Parameters.AddWithValue("$category", note.Category);
|
||||
command.Parameters.AddWithValue("$title", note.Title);
|
||||
command.Parameters.AddWithValue("$image", note.Image);
|
||||
command.Parameters.AddWithValue("$text", note.Text);
|
||||
command.Parameters.AddWithValue("$dateCreated", note.DateCreated.ToString("o")); // Сохраняем в формате ISO
|
||||
command.ExecuteNonQuery();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteNote(Note note)
|
||||
{
|
||||
if (string.IsNullOrEmpty(note.Id))
|
||||
{
|
||||
Console.WriteLine("Ошибка: У заметки отсутствует Id.");
|
||||
return;
|
||||
}
|
||||
|
||||
using (var connection = new SqliteConnection(_connectionString))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
var command = connection.CreateCommand();
|
||||
command.CommandText =
|
||||
@"
|
||||
DELETE FROM Notes
|
||||
WHERE Id = $id
|
||||
";
|
||||
command.Parameters.AddWithValue("$id", note.Id);
|
||||
command.ExecuteNonQuery();
|
||||
int result = command.ExecuteNonQuery();
|
||||
|
||||
Console.WriteLine(result > 0 ? "Заметка удалена из базы данных." : "Ошибка: Заметка не найдена в базе данных.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
61
NoteContent/EditorPage.xaml
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="NotesDataAnalyst.EditorPage"
|
||||
Title="">
|
||||
|
||||
<!-- Верхняя панель инструментов -->
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem Text="Сохранить" IconImageSource="save_icon.png" Priority="0" Order="Primary" Clicked="SaveButton_Clicked"/>
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
<!-- Основное содержимое страницы -->
|
||||
<ContentPage.Content>
|
||||
<StackLayout Padding="10" Spacing="1">
|
||||
|
||||
<!-- Категория -->
|
||||
<Label Text="Category" FontSize="18" TextColor="Gray"/>
|
||||
<Picker x:Name="categoryPicker"
|
||||
Title="Выберите категорию"
|
||||
ItemsSource="{Binding Categories}" />
|
||||
|
||||
<Label Text="Заголовок" FontSize="18" TextColor="Gray"/>
|
||||
<Entry x:Name="titleEditor" Placeholder="Введите заголовок" FontSize="16" />
|
||||
|
||||
<!-- Загрузка изображения -->
|
||||
|
||||
<!-- Дефолтное изображение -->
|
||||
<Image x:Name="imageButton"
|
||||
Source="dotnet_bot.png"
|
||||
HeightRequest="100"
|
||||
WidthRequest="100"
|
||||
Aspect="AspectFill">
|
||||
<Image.GestureRecognizers>
|
||||
<TapGestureRecognizer Tapped="OnImageTapped" />
|
||||
</Image.GestureRecognizers>
|
||||
</Image>
|
||||
|
||||
|
||||
|
||||
<Editor x:Name="textEditor" Placeholder="Введите текст заметки" FontSize="16" HeightRequest="400" />
|
||||
|
||||
<!-- Нижняя панель с кнопками Markdown -->
|
||||
<Grid BackgroundColor="Transparent" Padding="5" VerticalOptions="End" HorizontalOptions="Center">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Кнопки для редактирования Markdown -->
|
||||
<ImageButton Source="delete.png" Grid.Column="0" Command="{Binding InsertHeaderCommand}" CommandParameter="**Bold Text**"/>
|
||||
<ImageButton Source="delete.png" Grid.Column="1" Command="{Binding ShowLinkInputCommand}" CommandParameter="_Italic Text_"/>
|
||||
<ImageButton Source="pencil.png" Grid.Column="2" Command="{Binding AddLinkCommand}"/>
|
||||
<ImageButton Source="delete.png" Grid.Column="3" Command="{Binding InsertMarkdownCommand}" CommandParameter="# Header"/>
|
||||
<ImageButton Source="delete.png" Grid.Column="4" Command="{Binding ShowEmojiPopupCommand}" CommandParameter="- List Item"/>
|
||||
</Grid>
|
||||
</StackLayout>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
||||
301
NoteContent/EditorPage.xaml.cs
Normal file
|
|
@ -0,0 +1,301 @@
|
|||
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 = $"";
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
46
NoteContent/EmojiSelectionPopup.xaml
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<toolkit:Popup xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
|
||||
x:Class="NotesDataAnalyst.EmojiSelectionPopup">
|
||||
|
||||
<!-- Внутри Frame мы можем установить цвет фона -->
|
||||
<!-- Задаем фон внутри Frame -->
|
||||
<Frame BackgroundColor="White"
|
||||
CornerRadius="10"
|
||||
Padding="10"
|
||||
VerticalOptions="Center"
|
||||
HorizontalOptions="Center"
|
||||
WidthRequest="300">
|
||||
|
||||
<StackLayout>
|
||||
<Label Text="Выберите смайлик" FontSize="18" HorizontalOptions="Center" />
|
||||
|
||||
<!-- Прокручиваемая область для смайликов -->
|
||||
<ScrollView HeightRequest="200">
|
||||
<CollectionView x:Name="emojiCollectionView"
|
||||
ItemsSource="{Binding EmojiList}"
|
||||
SelectionMode="Single"
|
||||
SelectionChanged="OnEmojiSelected">
|
||||
<CollectionView.ItemsLayout>
|
||||
<GridItemsLayout Orientation="Vertical" Span="4" />
|
||||
</CollectionView.ItemsLayout>
|
||||
<CollectionView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Label Text="{Binding}"
|
||||
FontSize="24"
|
||||
HorizontalOptions="Center"
|
||||
VerticalOptions="Center"
|
||||
Padding="10" />
|
||||
</DataTemplate>
|
||||
</CollectionView.ItemTemplate>
|
||||
</CollectionView>
|
||||
</ScrollView>
|
||||
|
||||
<!-- Кнопка для закрытия окна -->
|
||||
<Button Text="Закрыть" Clicked="OnCloseButtonClicked" HorizontalOptions="Center" />
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
</toolkit:Popup>
|
||||
|
||||
|
||||
44
NoteContent/EmojiSelectionPopup.xaml.cs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
using CommunityToolkit.Maui.Views;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace NotesDataAnalyst;
|
||||
|
||||
public partial class EmojiSelectionPopup : Popup
|
||||
{
|
||||
public event Action<string>? EmojiSelected;
|
||||
|
||||
public ObservableCollection<string> EmojiList { get; set; }
|
||||
|
||||
public EmojiSelectionPopup()
|
||||
{
|
||||
InitializeComponent();
|
||||
EmojiList = new ObservableCollection<string>
|
||||
{
|
||||
"🌍", "😊", "🎉", "👍","📑","📝","✏️","📆","💼","👜","💄","⌚","💎","⛏️",
|
||||
"❤️", "🔥", "✨", "🚀",
|
||||
// Добавьте больше смайликов по мере необходимости
|
||||
};
|
||||
BindingContext = this;
|
||||
}
|
||||
|
||||
// Обработчик выбора смайлика
|
||||
|
||||
|
||||
|
||||
private void OnEmojiSelected(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (e.CurrentSelection.FirstOrDefault() is string selectedEmoji)
|
||||
{
|
||||
EmojiSelected?.Invoke(selectedEmoji);
|
||||
// Close(); // Используем Close для закрытия окна
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCloseButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
Close(); // Используем Close при нажатии на кнопку
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
70
NoteContent/FileLoader.cs
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
/*namespace NotesDataAnalyst
|
||||
{
|
||||
public static class FileLoader
|
||||
{
|
||||
// Загрузка одной заметки из указанного файла
|
||||
public static async Task<Note?> LoadDataAsync(string filePath)
|
||||
{
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
return null; // Если файл не существует, возвращаем null
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Чтение JSON-содержимого из файла
|
||||
string jsonString = await File.ReadAllTextAsync(filePath);
|
||||
|
||||
// Десериализация в объект Note
|
||||
Note? note = JsonSerializer.Deserialize<Note>(jsonString);
|
||||
if (note != null)
|
||||
{
|
||||
note.FilePath = filePath; // Устанавливаем путь к файлу, если загрузка успешна
|
||||
}
|
||||
|
||||
return note;
|
||||
}
|
||||
catch (JsonException ex)
|
||||
{
|
||||
Console.WriteLine($"Ошибка десериализации JSON: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Загрузка всех заметок из базовой папки
|
||||
/* public static async Task<List<Note>> LoadAllNotesAsync(string basePath)
|
||||
{
|
||||
var notes = new List<Note>();
|
||||
|
||||
// Проверяем, существует ли базовая папка
|
||||
if (!Directory.Exists(basePath))
|
||||
{
|
||||
return notes; // Если папки нет, возвращаем пустой список
|
||||
}
|
||||
|
||||
// Проходим по каждой папке категории
|
||||
foreach (string categoryFolder in Directory.GetDirectories(basePath))
|
||||
{
|
||||
// Проходим по всем JSON-файлам в папке категории
|
||||
foreach (string filePath in Directory.GetFiles(categoryFolder, "*.json"))
|
||||
{
|
||||
Note? note = await LoadDataAsync(filePath); // Загружаем заметку из файла
|
||||
if (note != null)
|
||||
{
|
||||
notes.Add(note); // Добавляем в список, если успешно загружено
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return notes; // Возвращаем список всех загруженных заметок
|
||||
}
|
||||
}
|
||||
}*/
|
||||
83
NoteContent/FileSaver.cs
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NotesDataAnalyst.NoteContent
|
||||
{
|
||||
public class FileSaver : INotifyPropertyChanged
|
||||
{
|
||||
// Базовый путь, где будут храниться все заметки
|
||||
private readonly string _basePath;
|
||||
private ObservableCollection<string> _files;
|
||||
|
||||
// Коллекция для хранения путей к сохранённым файлам
|
||||
public ObservableCollection<string> Files
|
||||
{
|
||||
get => _files;
|
||||
private set
|
||||
{
|
||||
_files = value;
|
||||
OnPropertyChanged(nameof(Files));
|
||||
}
|
||||
}
|
||||
|
||||
public FileSaver(string basePath)
|
||||
{
|
||||
// Устанавливаем базовый путь и инициализируем коллекцию файлов
|
||||
_basePath = basePath;
|
||||
Files = new ObservableCollection<string>();
|
||||
}
|
||||
|
||||
// Создаёт путь к файлу на основе категории и заголовка
|
||||
private string GenerateFilePath(Note note)
|
||||
{
|
||||
// Определяем путь для папки категории
|
||||
string categoryFolder = Path.Combine(_basePath, note.Category);
|
||||
|
||||
// Создаём папку, если её ещё нет
|
||||
Directory.CreateDirectory(categoryFolder);
|
||||
|
||||
// Преобразуем заголовок в имя файла, удаляя недопустимые символы
|
||||
string fileName = SanitizeFileName(note.Title) + ".json";
|
||||
|
||||
// Полный путь к файлу
|
||||
return Path.Combine(categoryFolder, fileName);
|
||||
}
|
||||
|
||||
// Удаляет недопустимые символы из заголовка для имени файла
|
||||
private string SanitizeFileName(string title)
|
||||
{
|
||||
// Заменяем символы, которые нельзя использовать в именах файлов, на подчёркивания
|
||||
return Regex.Replace(title, @"[<>:""/\|?*]", "_");
|
||||
}
|
||||
|
||||
public void SaveData(Note note)
|
||||
{
|
||||
// Если у заметки есть путь к файлу, обновляем существующий файл
|
||||
string filePath = !string.IsNullOrEmpty(note.FilePath)
|
||||
? note.FilePath
|
||||
: GenerateFilePath(note);
|
||||
|
||||
string jsonString = JsonSerializer.Serialize(note);
|
||||
File.WriteAllText(filePath, jsonString);
|
||||
|
||||
// Если это новая заметка, добавляем её путь в коллекцию
|
||||
if (!Files.Contains(filePath))
|
||||
{
|
||||
Files.Add(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
protected virtual void OnPropertyChanged(string propertyName) =>
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
20
NoteContent/LinkInputPopup.xaml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="NotesDataAnalyst.LinkInputPopup"
|
||||
BackgroundColor="Transparent"
|
||||
Padding="20">
|
||||
|
||||
<Frame BackgroundColor="White"
|
||||
CornerRadius="10"
|
||||
Padding="20"
|
||||
VerticalOptions="Center"
|
||||
HorizontalOptions="Center">
|
||||
<StackLayout>
|
||||
<Label Text="Введите URL ссылки" FontSize="18" HorizontalOptions="Center"/>
|
||||
<Entry x:Name="urlEntry" Placeholder="https://example.com" Keyboard="Url"/>
|
||||
<Button Text="Добавить" Clicked="OnAddButtonClicked"/>
|
||||
<Button Text="Отмена" Clicked="OnCancelButtonClicked"/>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
</ContentPage>
|
||||
33
NoteContent/LinkInputPopup.xaml.cs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
namespace NotesDataAnalyst;
|
||||
|
||||
public partial class LinkInputPopup : ContentPage
|
||||
{
|
||||
public event Action<string>? LinkSubmitted;
|
||||
|
||||
public LinkInputPopup()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnAddButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
string url = urlEntry.Text;
|
||||
|
||||
if (!string.IsNullOrEmpty(url))
|
||||
{
|
||||
LinkSubmitted?.Invoke(url); // Ïåðåäà÷à ââåäåííîé ññûëêè îáðàòíî
|
||||
ClosePopup();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCancelButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
ClosePopup();
|
||||
}
|
||||
|
||||
private void ClosePopup()
|
||||
{
|
||||
// Çàêðûòèå îêíà (èìèòèðóåì ïîâåäåíèå Popup)
|
||||
Application.Current.MainPage.Navigation.PopModalAsync();
|
||||
}
|
||||
}
|
||||
86
NoteContent/MainPage.xaml
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="NotesDataAnalyst.MainPage">
|
||||
|
||||
<!-- Панель инструментов для добавления новой заметки -->
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem Text="Add" IconImageSource="add_icon.png" Priority="0" Order="Primary" Clicked="AddNoteButton_Clicked"/>
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
<!-- Контейнер контента страницы -->
|
||||
<ContentPage.Content>
|
||||
<StackLayout Padding="20" Spacing="15">
|
||||
<!-- Панель поиска -->
|
||||
<SearchBar x:Name="searchBar"
|
||||
Placeholder="Поиск по заметкам"
|
||||
TextChanged="OnSearchTextChanged" />
|
||||
|
||||
<!-- Выпадающий список категорий -->
|
||||
<Picker x:Name="categoryPicker"
|
||||
Title="Выберите категорию"
|
||||
ItemsSource="{Binding Categories}"
|
||||
SelectedIndexChanged="OnCategorySelected" />
|
||||
|
||||
|
||||
|
||||
<!-- Коллекция заметок с возможностью прокрутки и анимацией -->
|
||||
<CollectionView x:Name="notesCollectionView"
|
||||
ItemsSource="{Binding Notes}"
|
||||
VerticalScrollBarVisibility="Always"
|
||||
HeightRequest="500">
|
||||
<!-- Устанавливаем высоту CollectionView -->
|
||||
|
||||
<!-- Настройка вертикального расположения с отступами -->
|
||||
<CollectionView.ItemsLayout>
|
||||
<LinearItemsLayout Orientation="Vertical" ItemSpacing="15"/>
|
||||
</CollectionView.ItemsLayout>
|
||||
|
||||
<!-- Шаблон отображения элемента -->
|
||||
<CollectionView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Frame Padding="0" Margin="5" CornerRadius="8" BackgroundColor="Transparent">
|
||||
<Frame.GestureRecognizers>
|
||||
<TapGestureRecognizer Tapped="OnNoteTapped" />
|
||||
</Frame.GestureRecognizers>
|
||||
|
||||
<!-- Содержимое элемента (изображение и заголовок) -->
|
||||
<StackLayout Orientation="Vertical"
|
||||
VerticalOptions="CenterAndExpand"
|
||||
HorizontalOptions="CenterAndExpand"
|
||||
WidthRequest="300"
|
||||
HeightRequest="150">
|
||||
|
||||
<!-- Изображение заметки -->
|
||||
<Image Source="{Binding Image}"
|
||||
Aspect="AspectFill"
|
||||
HeightRequest="120"
|
||||
WidthRequest="300"
|
||||
HorizontalOptions="Center"
|
||||
VerticalOptions="Center">
|
||||
<Image.Triggers>
|
||||
<DataTrigger TargetType="Image" Binding="{Binding Image}" Value="{x:Null}">
|
||||
<Setter Property="Source" Value="placeholder_image.png" />
|
||||
</DataTrigger>
|
||||
</Image.Triggers>
|
||||
</Image>
|
||||
|
||||
<!-- Заголовок заметки -->
|
||||
<Label Text="{Binding Title}"
|
||||
FontSize="18"
|
||||
FontAttributes="Bold"
|
||||
HorizontalOptions="Center"
|
||||
VerticalOptions="End"
|
||||
TextColor="Black" />
|
||||
</StackLayout>
|
||||
|
||||
</Frame>
|
||||
</DataTemplate>
|
||||
</CollectionView.ItemTemplate>
|
||||
</CollectionView>
|
||||
</StackLayout>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
||||
|
||||
|
||||
247
NoteContent/MainPage.xaml.cs
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
using System.Collections.ObjectModel;
|
||||
using NotesDataAnalyst.NoteContent;
|
||||
|
||||
namespace NotesDataAnalyst
|
||||
{
|
||||
// MainPage.xaml.cs
|
||||
|
||||
|
||||
public partial class MainPage : ContentPage
|
||||
{
|
||||
public DateTime DateCreated { get; set; } = DateTime.UtcNow;
|
||||
public ObservableCollection<Note> Notes { get; set; }
|
||||
public ObservableCollection<Note> FilteredNotes { get; set; }
|
||||
|
||||
public MainPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
|
||||
BindingContext = this;
|
||||
|
||||
|
||||
// Подписываемся на сообщения для обновления списка заметок
|
||||
MessagingCenter.Subscribe<EditorPage, Note>(this, "NoteSaved", (sender, savedNote) =>
|
||||
{
|
||||
var existingNote = Notes.FirstOrDefault(n => n.Id == savedNote.Id);
|
||||
if (existingNote != null)
|
||||
{
|
||||
var index = Notes.IndexOf(existingNote);
|
||||
Notes.Remove(existingNote);
|
||||
Notes.Insert(0, savedNote);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Вставляем новую заметку в начало списка
|
||||
Notes.Insert(0, savedNote);
|
||||
}
|
||||
ApplyCategoryFilter();
|
||||
});
|
||||
|
||||
|
||||
MessagingCenter.Subscribe<NoteDetailPage, Note>(this, "NoteDeleted", (sender, deletedNote) =>
|
||||
{
|
||||
Notes.Remove(deletedNote);
|
||||
ApplyCategoryFilter();
|
||||
});
|
||||
|
||||
// Загружаем заметки из базы данных
|
||||
Notes = App.Database.GetAllNotes();
|
||||
|
||||
// Инициализация и загрузка данных
|
||||
CategoryManager.LoadCategories();
|
||||
categoryPicker.ItemsSource = CategoryManager.Categories;
|
||||
categoryPicker.SelectedItem = CategoryManager.ActiveCategory ?? CategoryManager.Categories.FirstOrDefault();
|
||||
// Notes = new ObservableCollection<Note>();
|
||||
FilteredNotes = new ObservableCollection<Note>();
|
||||
BindingContext = this;
|
||||
}
|
||||
|
||||
protected override async void OnAppearing()
|
||||
{
|
||||
base.OnAppearing();
|
||||
|
||||
// Загружаем отсортированные заметки
|
||||
Notes = new ObservableCollection<Note>(App.Database.GetAllNotes().OrderByDescending(n => n.DateCreated));
|
||||
|
||||
// Применяем фильтрацию
|
||||
ApplyCategoryFilter();
|
||||
|
||||
// Обновляем выбранную категорию в Picker
|
||||
categoryPicker.SelectedItem = CategoryManager.ActiveCategory;
|
||||
}
|
||||
|
||||
|
||||
/* private void OnCollectionViewScrolled(object sender, ItemsViewScrolledEventArgs e)
|
||||
{
|
||||
// Получаем центр экрана по оси Y
|
||||
double centerScreenY = notesCollectionView.Height / 2;
|
||||
|
||||
// Высота элемента (подберите в зависимости от реальной высоты элементов в CollectionView)
|
||||
double itemHeight = 150;
|
||||
|
||||
// Итерируем видимые элементы по их индексам
|
||||
for (int i = e.FirstVisibleItemIndex; i <= e.LastVisibleItemIndex; i++)
|
||||
{
|
||||
// Находим элемент с индексом i
|
||||
var note = Notes[i]; // предполагаем, что Notes - ObservableCollection<Note>
|
||||
|
||||
// Получаем фрейм элемента через шаблон
|
||||
var item = notesCollectionView.ItemTemplate.CreateContent() as Frame;
|
||||
if (item == null) continue;
|
||||
|
||||
// Устанавливаем BindingContext для анимации текущего элемента
|
||||
item.BindingContext = note;
|
||||
|
||||
// Позиция центра элемента
|
||||
double itemCenterY = (i * itemHeight) + (itemHeight / 2);
|
||||
|
||||
// Расчёт расстояния до центра экрана
|
||||
double distanceFromCenter = Math.Abs(centerScreenY - itemCenterY);
|
||||
|
||||
// Настройка масштаба и прозрачности
|
||||
double scale = Math.Max(0.75, 1 - (distanceFromCenter / centerScreenY));
|
||||
double opacity = Math.Max(0.5, 1 - (distanceFromCenter / centerScreenY));
|
||||
|
||||
// Анимации: масштабирование и изменение прозрачности
|
||||
item.ScaleTo(scale, 250, Easing.CubicInOut);
|
||||
item.FadeTo(opacity, 250, Easing.CubicInOut);
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
|
||||
private async void OnNoteTapped(object sender, EventArgs e)
|
||||
{
|
||||
// Получаем контекст заметки, на которую был выполнен клик
|
||||
var frame = sender as Frame;
|
||||
var selectedNote = frame?.BindingContext as Note;
|
||||
|
||||
if (selectedNote != null)
|
||||
{
|
||||
// Переход на страницу NoteDetailPage с выбранной заметкой
|
||||
await Navigation.PushAsync(new NoteDetailPage(selectedNote));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Обработчик для изменения текста в панели поиска
|
||||
private void OnSearchTextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
ApplySearchFilter(e.NewTextValue);
|
||||
}
|
||||
|
||||
private void ApplySearchFilter(string searchText)
|
||||
{
|
||||
FilteredNotes.Clear();
|
||||
var filteredNotes = Notes
|
||||
.Where(note => string.IsNullOrEmpty(searchText) ||
|
||||
(note.Title?.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) >= 0))
|
||||
.ToList();
|
||||
|
||||
foreach (var note in filteredNotes)
|
||||
{
|
||||
FilteredNotes.Add(note);
|
||||
}
|
||||
}
|
||||
|
||||
private ObservableCollection<Note> LoadNotes()
|
||||
{
|
||||
// Здесь загружаем заметки из базы данных или локального хранилища
|
||||
return new ObservableCollection<Note>();
|
||||
}
|
||||
|
||||
// Обработчик для изменения выбранной категории
|
||||
private void OnCategorySelected(object sender, EventArgs e)
|
||||
{
|
||||
// Проверяем, что categoryPicker.SelectedItem не является null
|
||||
if (categoryPicker.SelectedItem == null)
|
||||
return;
|
||||
|
||||
string selectedCategory = categoryPicker.SelectedItem as string;
|
||||
|
||||
// Устанавливаем активную категорию
|
||||
CategoryManager.ActiveCategory = selectedCategory;
|
||||
|
||||
// Проверяем, что Notes и selectedCategory не null перед фильтрацией
|
||||
if (Notes == null || selectedCategory == null)
|
||||
{
|
||||
FilteredNotes = new ObservableCollection<Note>(Notes ?? new ObservableCollection<Note>());
|
||||
}
|
||||
else if (selectedCategory == "Все категории")
|
||||
{
|
||||
FilteredNotes = new ObservableCollection<Note>(Notes);
|
||||
}
|
||||
else
|
||||
{
|
||||
FilteredNotes = new ObservableCollection<Note>(Notes.Where(note => note.Category == selectedCategory));
|
||||
}
|
||||
|
||||
// Обновляем привязку данных CollectionView
|
||||
notesCollectionView.ItemsSource = FilteredNotes;
|
||||
}
|
||||
|
||||
protected override void OnDisappearing()
|
||||
{
|
||||
base.OnDisappearing();
|
||||
|
||||
// Отписываемся от сообщения при закрытии страницы
|
||||
MessagingCenter.Unsubscribe<NoteDetailPage, Note>(this, "NoteDeleted");
|
||||
}
|
||||
|
||||
private async void OnNoteSelected(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (e.CurrentSelection.FirstOrDefault() is Note selectedNote)
|
||||
{
|
||||
// Переход на NoteDetailPage вместо EditorPage
|
||||
await Navigation.PushAsync(new NoteDetailPage(selectedNote));
|
||||
}
|
||||
|
||||
((CollectionView)sender).SelectedItem = null;
|
||||
}
|
||||
|
||||
|
||||
/* protected override async void OnAppearing()
|
||||
{
|
||||
base.OnAppearing();
|
||||
|
||||
// Загружаем заметки асинхронно
|
||||
// Notes = await LoadNotesAsync();
|
||||
|
||||
// Применяем фильтрацию на основе `ActiveCategory`
|
||||
ApplyCategoryFilter();
|
||||
|
||||
// Обновляем `Picker` с категориями
|
||||
categoryPicker.SelectedItem = CategoryManager.ActiveCategory;
|
||||
}*/
|
||||
|
||||
private void ApplyCategoryFilter()
|
||||
{
|
||||
if (CategoryManager.ActiveCategory == "Все категории" || string.IsNullOrEmpty(CategoryManager.ActiveCategory))
|
||||
{
|
||||
FilteredNotes = new ObservableCollection<Note>(Notes);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Фильтрация по категории
|
||||
FilteredNotes = new ObservableCollection<Note>(Notes.Where(note => note.Category == CategoryManager.ActiveCategory));
|
||||
}
|
||||
|
||||
// Обновляем привязку данных для CollectionView
|
||||
notesCollectionView.ItemsSource = FilteredNotes;
|
||||
}
|
||||
|
||||
|
||||
private async void AddNoteButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
// Создаём новую пустую заметку
|
||||
var newNote = new Note();
|
||||
|
||||
// Переход на EditorPage с новой заметкой
|
||||
await Navigation.PushAsync(new EditorPage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
65
NoteContent/Note.cs
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Markdig;
|
||||
|
||||
|
||||
namespace NotesDataAnalyst.NoteContent
|
||||
{
|
||||
|
||||
|
||||
public static class MarkdownExtensions
|
||||
{
|
||||
public static string ToHtml(string markdownText)
|
||||
{
|
||||
// Создание конвейера с необходимыми расширениями
|
||||
var pipeline = new MarkdownPipelineBuilder()
|
||||
.UseAdvancedExtensions() // Подключение большинства популярных расширений
|
||||
.UseEmojiAndSmiley() // Поддержка эмодзи и смайлов
|
||||
.UseTaskLists() // Поддержка списков задач
|
||||
.UseDiagrams() // Поддержка диаграмм
|
||||
|
||||
.Build();
|
||||
|
||||
return Markdown.ToHtml(markdownText, pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class Note
|
||||
{
|
||||
public string Id { get; set; } = Guid.NewGuid().ToString(); // Уникальный идентификатор для заметки
|
||||
|
||||
// Категория заметки (например, "Личное", "Работа", и т.д.)
|
||||
public string Category { get; set; }
|
||||
|
||||
// Заголовок заметки, используется также как часть имени файла
|
||||
public string Title { get; set; }
|
||||
|
||||
// Поле для хранения ссылки на изображение
|
||||
public string Image { get; set; }
|
||||
|
||||
// Основной текст заметки, который пользователь может вводить в формате Markdown
|
||||
public string Text { get; set; }
|
||||
|
||||
// Свойство для пути к файлу заметки
|
||||
public string FilePath { get; set; }
|
||||
|
||||
public DateTime DateCreated { get; set; } = DateTime.UtcNow;
|
||||
|
||||
// Свойство для отображения текста в формате HTML
|
||||
// Используем Markdig для преобразования текста из Markdown в HTML
|
||||
public string FormattedText => MarkdownExtensions.ToHtml(Text);
|
||||
|
||||
|
||||
public string FormattedTitle => MarkdownExtensions.ToHtml(Title);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
49
NoteContent/NoteDetailPage.xaml
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="NotesDataAnalyst.NoteDetailPage"
|
||||
Title="">
|
||||
|
||||
<ContentPage.Content>
|
||||
<StackLayout Padding="10" Spacing="10">
|
||||
<!-- Заголовок заметки -->
|
||||
<Label x:Name="titleLabel"
|
||||
FontSize="24"
|
||||
FontAttributes="Bold"
|
||||
TextColor="Black"
|
||||
HorizontalOptions="Center" />
|
||||
|
||||
<!-- Изображение (если указано) -->
|
||||
<Image x:Name="imageView"
|
||||
HeightRequest="150"
|
||||
Aspect="AspectFill"
|
||||
IsVisible="False" />
|
||||
|
||||
<!-- Текст заметки -->
|
||||
<WebView x:Name="contentWebView" HeightRequest="430" Navigating="OnWebViewNavigating">
|
||||
<WebView.Source>
|
||||
<HtmlWebViewSource Html="{Binding FormattedText}"/>
|
||||
</WebView.Source>
|
||||
</WebView>
|
||||
|
||||
<!-- Кнопки "Редактировать" и "Удалить" -->
|
||||
<StackLayout Orientation="Horizontal" HorizontalOptions="Center" Spacing="20">
|
||||
<Button Text="Редактировать"
|
||||
BackgroundColor="#4CAF50"
|
||||
TextColor="White"
|
||||
Clicked="OnEditButtonClicked" />
|
||||
|
||||
<Button Text="Удалить"
|
||||
BackgroundColor="#f44336"
|
||||
TextColor="White"
|
||||
Clicked="OnDeleteButtonClicked" />
|
||||
|
||||
|
||||
|
||||
</StackLayout>
|
||||
|
||||
</StackLayout>
|
||||
|
||||
</ContentPage.Content>
|
||||
|
||||
</ContentPage>
|
||||
135
NoteContent/NoteDetailPage.xaml.cs
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
using Markdig.Syntax.Inlines;
|
||||
using Markdig;
|
||||
using System.Text.RegularExpressions;
|
||||
using Markdig.Renderers.Html;
|
||||
using Markdig.Syntax;
|
||||
using System.Collections.ObjectModel;
|
||||
using NotesDataAnalyst.NoteContent;
|
||||
|
||||
|
||||
namespace NotesDataAnalyst;
|
||||
|
||||
public partial class NoteDetailPage : ContentPage
|
||||
{
|
||||
private readonly Note _note;
|
||||
|
||||
|
||||
public NoteDetailPage(Note note)
|
||||
{
|
||||
InitializeComponent();
|
||||
_note = note;
|
||||
|
||||
// Óñòàíàâëèâàåì äàííûå çàìåòêè â ýëåìåíòû óïðàâëåíèÿ
|
||||
titleLabel.Text = _note.Title;
|
||||
//textLabel.Text = _note.Text;
|
||||
BindingContext = _note;
|
||||
|
||||
if (!string.IsNullOrEmpty(_note.Image))
|
||||
{
|
||||
imageView.Source = _note.Image;
|
||||
imageView.IsVisible = true;
|
||||
}
|
||||
|
||||
ApplyThemeToHtml(); // Ïðèìåíÿåì òåìó ê HTML-êîíòåíòó WebView
|
||||
}
|
||||
|
||||
/// //////////////////////////////////// Ðàáîòàåì ñ òåìîé Webwiev
|
||||
|
||||
|
||||
private void ApplyThemeToHtml()
|
||||
{
|
||||
bool isDarkTheme = Application.Current.RequestedTheme == AppTheme.Dark;
|
||||
string backgroundColor = isDarkTheme ? "#212121" : "#FFFFFF";
|
||||
string textColor = isDarkTheme ? "#FFFFFF" : "#000000";
|
||||
|
||||
// Ôîðìèðóåì HTML-êîíòåíò ñ CSS-ñòèëÿìè
|
||||
string htmlContent = $@"
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body {{
|
||||
background-color: {backgroundColor};
|
||||
color: {textColor};
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 10px;
|
||||
}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
{_note.FormattedText}
|
||||
</body>
|
||||
</html>";
|
||||
|
||||
contentWebView.Source = new HtmlWebViewSource { Html = htmlContent };
|
||||
}
|
||||
|
||||
protected override void OnAppearing()
|
||||
{
|
||||
base.OnAppearing();
|
||||
Application.Current.RequestedThemeChanged += OnRequestedThemeChanged;
|
||||
}
|
||||
|
||||
protected override void OnDisappearing()
|
||||
{
|
||||
base.OnDisappearing();
|
||||
Application.Current.RequestedThemeChanged -= OnRequestedThemeChanged;
|
||||
}
|
||||
|
||||
private void OnRequestedThemeChanged(object sender, AppThemeChangedEventArgs e)
|
||||
{
|
||||
ApplyThemeToHtml(); // Ïåðåçàãðóæàåì HTML ñ íîâîé òåìîé
|
||||
}
|
||||
|
||||
/// //////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// Îáðàáîò÷èê íàâèãàöèè WebView äëÿ ïåðåõâàòà ññûëîê
|
||||
private async void OnWebViewNavigating(object sender, WebNavigatingEventArgs e)
|
||||
{
|
||||
if (e.Url.StartsWith("note:"))
|
||||
{
|
||||
e.Cancel = true; // Îòìåíÿåì ïåðåõîä
|
||||
|
||||
// Èçâëåêàåì Id çàìåòêè èç ññûëêè
|
||||
string noteId = e.Url.Replace("note:", "");
|
||||
await NoteLinkManager.NavigateToNoteByIdAsync(noteId, Navigation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Îáðàáîò÷èê êíîïêè "Ðåäàêòèðîâàòü"
|
||||
private async void OnEditButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
// Âìåñòî ïåðåäà÷è _note.FilePath ïåðåäàåì ñàì îáúåêò _note
|
||||
await Navigation.PushAsync(new EditorPage(_note));
|
||||
}
|
||||
|
||||
// Îáðàáîò÷èê êíîïêè "Óäàëèòü"
|
||||
private async void OnDeleteButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
bool confirm = await DisplayAlert("Ïîäòâåðæäåíèå", "Âû óâåðåíû, ÷òî õîòèòå óäàëèòü ýòó çàìåòêó?", "Óäàëèòü", "Îòìåíà");
|
||||
if (confirm)
|
||||
{
|
||||
// Óäàëÿåì ôàéë çàìåòêè
|
||||
// if (File.Exists(_note.FilePath))
|
||||
// { //Óäàëåíèå èç ÁÄ ïîêà íå ðàáîòàåò
|
||||
// await Task.Run (() => App.DbContext.DeleteNote(_note));
|
||||
// File.Delete(_note.FilePath);
|
||||
// Óäàëÿåì çàìåòêó èç áàçû äàííûõ
|
||||
App.Database.DeleteNote(_note);
|
||||
await DisplayAlert("Îïîâåùåíèå", "Ôàéë óäàëåí", "Ok");
|
||||
// Îòïðàâëÿåì ñîîáùåíèå äëÿ îáíîâëåíèÿ ñïèñêà çàìåòîê
|
||||
MessagingCenter.Send(this, "NoteDeleted", _note);
|
||||
// Âîçâðàùàåìñÿ íà ãëàâíóþ ñòðàíèöó è îáíîâëÿåì ñïèñîê
|
||||
await Navigation.PushAsync(new MainPage());
|
||||
// }
|
||||
// else { await DisplayAlert("Îøèáêà", "Çàïèñü íå ìîæåò áûòü óäàëåíà, òàê êàê ôàéë íå íàéäåí", "Ok"); }
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
48
NoteContent/NoteLinkManager.cs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Maui.Controls;
|
||||
|
||||
namespace NotesDataAnalyst.NoteContent
|
||||
{
|
||||
public static class NoteLinkManager
|
||||
{
|
||||
private static readonly Regex LinkPattern = new(@"<a href=""note:(.*?)"">(.*?)</a>", RegexOptions.Compiled);
|
||||
|
||||
// Метод для вставки HTML-ссылки на заметку
|
||||
public static string InsertLink(string currentText, Note selectedNote)
|
||||
{
|
||||
string linkText = $"<a href=\"note:{selectedNote.Id}\">{selectedNote.Title}</a>";
|
||||
return currentText + " " + linkText;
|
||||
}
|
||||
|
||||
// Метод для извлечения ссылок в HTML
|
||||
public static List<(string Id, string Title)> ParseLinks(string html)
|
||||
{
|
||||
var links = new List<(string Id, string Title)>();
|
||||
var matches = LinkPattern.Matches(html);
|
||||
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
string id = match.Groups[1].Value;
|
||||
string title = match.Groups[2].Value;
|
||||
links.Add((id, title));
|
||||
}
|
||||
|
||||
return links;
|
||||
}
|
||||
|
||||
// Реализуем метод NavigateToNoteByIdAsync для перехода к заметке по Id
|
||||
public static async Task NavigateToNoteByIdAsync(string noteId, INavigation navigation)
|
||||
{
|
||||
var note = App.Database.GetAllNotes().FirstOrDefault(n => n.Id == noteId);
|
||||
if (note != null)
|
||||
{
|
||||
await navigation.PushAsync(new NoteDetailPage(note));
|
||||
}
|
||||
else
|
||||
{
|
||||
await Application.Current.MainPage.DisplayAlert("Ошибка", "Заметка не найдена", "OK");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
31
NoteContent/NoteSelectionPopup.xaml
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<toolkit:Popup xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
|
||||
x:Class="NotesDataAnalyst.NoteSelectionPopup">
|
||||
|
||||
<StackLayout Padding="20" BackgroundColor="White" WidthRequest="300">
|
||||
<Label Text="Выберите заметку для ссылки" FontSize="18" FontAttributes="Bold" HorizontalOptions="Center" />
|
||||
|
||||
<SearchBar x:Name="searchBar" Placeholder="Поиск заметок" TextChanged="OnSearchTextChanged" />
|
||||
|
||||
<CollectionView x:Name="notesCollectionView" SelectionMode="Single" SelectionChanged="OnNoteSelected">
|
||||
<CollectionView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Frame Padding="10" Margin="5" BackgroundColor="LightGray" CornerRadius="8">
|
||||
|
||||
<Frame.GestureRecognizers>
|
||||
<TapGestureRecognizer Tapped="OnNoteTapped" />
|
||||
</Frame.GestureRecognizers>
|
||||
|
||||
<Label Text="{Binding Title}" FontSize="16" TextColor="Black" />
|
||||
</Frame>
|
||||
|
||||
</DataTemplate>
|
||||
</CollectionView.ItemTemplate>
|
||||
</CollectionView>
|
||||
|
||||
<Button Text="Отмена" Clicked="OnCancelButtonClicked" BackgroundColor="#f44336" TextColor="White"/>
|
||||
</StackLayout>
|
||||
</toolkit:Popup>
|
||||
|
||||
59
NoteContent/NoteSelectionPopup.xaml.cs
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
using CommunityToolkit.Maui.Views;
|
||||
using NotesDataAnalyst.NoteContent;
|
||||
|
||||
|
||||
namespace NotesDataAnalyst
|
||||
{
|
||||
public partial class NoteSelectionPopup : Popup
|
||||
{
|
||||
public event Action<Note> NoteSelected;
|
||||
|
||||
public NoteSelectionPopup()
|
||||
{
|
||||
InitializeComponent();
|
||||
notesCollectionView.ItemsSource = App.Database.GetAllNotes(); // Çàãðóçêà çàìåòîê èç ÁÄ
|
||||
}
|
||||
|
||||
private void OnSearchTextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
string searchText = e.NewTextValue.ToLower();
|
||||
notesCollectionView.ItemsSource = App.Database.GetAllNotes()
|
||||
.Where(note => note.Title.ToLower().Contains(searchText));
|
||||
}
|
||||
|
||||
private async void OnNoteSelected(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
|
||||
|
||||
if (e.CurrentSelection.FirstOrDefault() is Note selectedNote)
|
||||
{
|
||||
|
||||
NoteSelected?.Invoke(selectedNote);
|
||||
Close(); // Çàêðûâàåì îêíî ïîñëå âûáîðà çàìåòêè
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnNoteTapped(object sender, EventArgs e)
|
||||
{
|
||||
// Ïîëó÷àåì ýëåìåíò, íà êîòîðûé êëèêíóëè
|
||||
var tappedFrame = (Frame)sender;
|
||||
var selectedNote = (Note)tappedFrame.BindingContext;
|
||||
|
||||
if (selectedNote != null)
|
||||
{
|
||||
NoteSelected?.Invoke(selectedNote);
|
||||
Close(); // Çàêðûâàåì îêíî ïîñëå âûáîðà çàìåòêè
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void OnCancelButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
Close(); // Çàêðûòèå îêíà ïî íàæàòèþ íà êíîïêó Îòìåíà
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
89
NotesDataAnalyst.csproj
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
|
||||
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks>
|
||||
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
|
||||
<!-- <TargetFrameworks>$(TargetFrameworks);net8.0-tizen</TargetFrameworks> -->
|
||||
|
||||
<!-- Note for MacCatalyst:
|
||||
The default runtime is maccatalyst-x64, except in Release config, in which case the default is maccatalyst-x64;maccatalyst-arm64.
|
||||
When specifying both architectures, use the plural <RuntimeIdentifiers> instead of the singular <RuntimeIdentifier>.
|
||||
The Mac App Store will NOT accept apps with ONLY maccatalyst-arm64 indicated;
|
||||
either BOTH runtimes must be indicated or ONLY macatalyst-x64. -->
|
||||
<!-- For example: <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers> -->
|
||||
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>NotesDataAnalyst</RootNamespace>
|
||||
<UseMaui>true</UseMaui>
|
||||
<SingleProject>true</SingleProject>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<!-- Display name -->
|
||||
<ApplicationTitle>NotesDataAnalyst</ApplicationTitle>
|
||||
|
||||
<!-- App Identifier -->
|
||||
<ApplicationId>com.companyname.notesdataanalyst</ApplicationId>
|
||||
|
||||
<!-- Versions -->
|
||||
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
|
||||
<ApplicationVersion>1</ApplicationVersion>
|
||||
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">11.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">13.1</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
|
||||
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- App Icon -->
|
||||
<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" />
|
||||
|
||||
<!-- Splash Screen -->
|
||||
<MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" />
|
||||
|
||||
<!-- Images -->
|
||||
<MauiImage Include="Resources\Images\*" />
|
||||
<MauiImage Update="Resources\Images\dotnet_bot.png" Resize="True" BaseSize="300,185" />
|
||||
|
||||
<!-- Custom Fonts -->
|
||||
<MauiFont Include="Resources\Fonts\*" />
|
||||
|
||||
<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
|
||||
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommunityToolkit.Maui" Version="9.1.0" />
|
||||
<PackageReference Include="Markdig" Version="0.38.0" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.0-rc.2.24474.1" />
|
||||
<PackageReference Include="Microsoft.Maui.Controls" Version="8.0.92" />
|
||||
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="$(MauiVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<MauiXaml Update="GraphPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="NoteContent\EditorPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="NoteContent\EmojiSelectionPopup.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="NoteContent\LinkInputPopup.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="NoteContent\NoteDetailPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
<MauiXaml Update="NoteContent\NoteSelectionPopup.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</MauiXaml>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
27
NotesDataAnalyst.sln
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.9.34728.123
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NotesDataAnalyst", "NotesDataAnalyst.csproj", "{8AAA7775-10E2-43A6-ACB4-DDD53C514A9E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{8AAA7775-10E2-43A6-ACB4-DDD53C514A9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8AAA7775-10E2-43A6-ACB4-DDD53C514A9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8AAA7775-10E2-43A6-ACB4-DDD53C514A9E}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{8AAA7775-10E2-43A6-ACB4-DDD53C514A9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8AAA7775-10E2-43A6-ACB4-DDD53C514A9E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8AAA7775-10E2-43A6-ACB4-DDD53C514A9E}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {BB40F5E4-7F23-47F8-9832-56F12E8279A1}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
6
Platforms/Android/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
</manifest>
|
||||
11
Platforms/Android/MainActivity.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using Android.App;
|
||||
using Android.Content.PM;
|
||||
using Android.OS;
|
||||
|
||||
namespace NotesDataAnalyst
|
||||
{
|
||||
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
|
||||
public class MainActivity : MauiAppCompatActivity
|
||||
{
|
||||
}
|
||||
}
|
||||
16
Platforms/Android/MainApplication.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using Android.App;
|
||||
using Android.Runtime;
|
||||
|
||||
namespace NotesDataAnalyst
|
||||
{
|
||||
[Application]
|
||||
public class MainApplication : MauiApplication
|
||||
{
|
||||
public MainApplication(IntPtr handle, JniHandleOwnership ownership)
|
||||
: base(handle, ownership)
|
||||
{
|
||||
}
|
||||
|
||||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||
}
|
||||
}
|
||||
6
Platforms/Android/Resources/values/colors.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#512BD4</color>
|
||||
<color name="colorPrimaryDark">#2B0B98</color>
|
||||
<color name="colorAccent">#2B0B98</color>
|
||||
</resources>
|
||||
10
Platforms/MacCatalyst/AppDelegate.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
using Foundation;
|
||||
|
||||
namespace NotesDataAnalyst
|
||||
{
|
||||
[Register("AppDelegate")]
|
||||
public class AppDelegate : MauiUIApplicationDelegate
|
||||
{
|
||||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||
}
|
||||
}
|
||||
14
Platforms/MacCatalyst/Entitlements.plist
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<!-- See https://aka.ms/maui-publish-app-store#add-entitlements for more information about adding entitlements.-->
|
||||
<dict>
|
||||
<!-- App Sandbox must be enabled to distribute a MacCatalyst app through the Mac App Store. -->
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<!-- When App Sandbox is enabled, this value is required to open outgoing network connections. -->
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
38
Platforms/MacCatalyst/Info.plist
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<!-- The Mac App Store requires you specify if the app uses encryption. -->
|
||||
<!-- Please consult https://developer.apple.com/documentation/bundleresources/information_property_list/itsappusesnonexemptencryption -->
|
||||
<!-- <key>ITSAppUsesNonExemptEncryption</key> -->
|
||||
<!-- Please indicate <true/> or <false/> here. -->
|
||||
|
||||
<!-- Specify the category for your app here. -->
|
||||
<!-- Please consult https://developer.apple.com/documentation/bundleresources/information_property_list/lsapplicationcategorytype -->
|
||||
<!-- <key>LSApplicationCategoryType</key> -->
|
||||
<!-- <string>public.app-category.YOUR-CATEGORY-HERE</string> -->
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>XSAppIconAssets</key>
|
||||
<string>Assets.xcassets/appicon.appiconset</string>
|
||||
</dict>
|
||||
</plist>
|
||||
16
Platforms/MacCatalyst/Program.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using ObjCRuntime;
|
||||
using UIKit;
|
||||
|
||||
namespace NotesDataAnalyst
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
// This is the main entry point of the application.
|
||||
static void Main(string[] args)
|
||||
{
|
||||
// if you want to use a different Application Delegate class from "AppDelegate"
|
||||
// you can specify it here.
|
||||
UIApplication.Main(args, null, typeof(AppDelegate));
|
||||
}
|
||||
}
|
||||
}
|
||||
17
Platforms/Tizen/Main.cs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
using Microsoft.Maui;
|
||||
using Microsoft.Maui.Hosting;
|
||||
using System;
|
||||
|
||||
namespace NotesDataAnalyst
|
||||
{
|
||||
internal class Program : MauiApplication
|
||||
{
|
||||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
var app = new Program();
|
||||
app.Run(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Platforms/Tizen/tizen-manifest.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="maui-application-id-placeholder" version="0.0.0" api-version="8" xmlns="http://tizen.org/ns/packages">
|
||||
<profile name="common" />
|
||||
<ui-application appid="maui-application-id-placeholder" exec="NotesDataAnalyst.dll" multiple="false" nodisplay="false" taskmanage="true" type="dotnet" launch_mode="single">
|
||||
<label>maui-application-title-placeholder</label>
|
||||
<icon>maui-appicon-placeholder</icon>
|
||||
<metadata key="http://tizen.org/metadata/prefer_dotnet_aot" value="true" />
|
||||
</ui-application>
|
||||
<shortcut-list />
|
||||
<privileges>
|
||||
<privilege>http://tizen.org/privilege/internet</privilege>
|
||||
</privileges>
|
||||
<dependencies />
|
||||
<provides-appdefined-privileges />
|
||||
</manifest>
|
||||
8
Platforms/Windows/App.xaml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<maui:MauiWinUIApplication
|
||||
x:Class="NotesDataAnalyst.WinUI.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:maui="using:Microsoft.Maui"
|
||||
xmlns:local="using:NotesDataAnalyst.WinUI">
|
||||
|
||||
</maui:MauiWinUIApplication>
|
||||
25
Platforms/Windows/App.xaml.cs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
using Microsoft.UI.Xaml;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
|
||||
namespace NotesDataAnalyst.WinUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides application-specific behavior to supplement the default Application class.
|
||||
/// </summary>
|
||||
public partial class App : MauiWinUIApplication
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the singleton application object. This is the first line of authored code
|
||||
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||
/// </summary>
|
||||
public App()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||
}
|
||||
|
||||
}
|
||||
46
Platforms/Windows/Package.appxmanifest
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package
|
||||
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
|
||||
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
|
||||
IgnorableNamespaces="uap rescap">
|
||||
|
||||
<Identity Name="maui-package-name-placeholder" Publisher="CN=User Name" Version="0.0.0.0" />
|
||||
|
||||
<mp:PhoneIdentity PhoneProductId="B0B711CC-EE95-4BD5-88F0-97C4A359FA13" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||
|
||||
<Properties>
|
||||
<DisplayName>$placeholder$</DisplayName>
|
||||
<PublisherDisplayName>User Name</PublisherDisplayName>
|
||||
<Logo>$placeholder$.png</Logo>
|
||||
</Properties>
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||
</Dependencies>
|
||||
|
||||
<Resources>
|
||||
<Resource Language="x-generate" />
|
||||
</Resources>
|
||||
|
||||
<Applications>
|
||||
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$">
|
||||
<uap:VisualElements
|
||||
DisplayName="$placeholder$"
|
||||
Description="$placeholder$"
|
||||
Square150x150Logo="$placeholder$.png"
|
||||
Square44x44Logo="$placeholder$.png"
|
||||
BackgroundColor="transparent">
|
||||
<uap:DefaultTile Square71x71Logo="$placeholder$.png" Wide310x150Logo="$placeholder$.png" Square310x310Logo="$placeholder$.png" />
|
||||
<uap:SplashScreen Image="$placeholder$.png" />
|
||||
</uap:VisualElements>
|
||||
</Application>
|
||||
</Applications>
|
||||
|
||||
<Capabilities>
|
||||
<rescap:Capability Name="runFullTrust" />
|
||||
</Capabilities>
|
||||
|
||||
</Package>
|
||||
15
Platforms/Windows/app.manifest
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="NotesDataAnalyst.WinUI.app"/>
|
||||
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<!-- The combination of below two tags have the following effect:
|
||||
1) Per-Monitor for >= Windows 10 Anniversary Update
|
||||
2) System < Windows 10 Anniversary Update
|
||||
-->
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
</assembly>
|
||||
10
Platforms/iOS/AppDelegate.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
using Foundation;
|
||||
|
||||
namespace NotesDataAnalyst
|
||||
{
|
||||
[Register("AppDelegate")]
|
||||
public class AppDelegate : MauiUIApplicationDelegate
|
||||
{
|
||||
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||
}
|
||||
}
|
||||
32
Platforms/iOS/Info.plist
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>XSAppIconAssets</key>
|
||||
<string>Assets.xcassets/appicon.appiconset</string>
|
||||
</dict>
|
||||
</plist>
|
||||
16
Platforms/iOS/Program.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using ObjCRuntime;
|
||||
using UIKit;
|
||||
|
||||
namespace NotesDataAnalyst
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
// This is the main entry point of the application.
|
||||
static void Main(string[] args)
|
||||
{
|
||||
// if you want to use a different Application Delegate class from "AppDelegate"
|
||||
// you can specify it here.
|
||||
UIApplication.Main(args, null, typeof(AppDelegate));
|
||||
}
|
||||
}
|
||||
}
|
||||
8
Properties/launchSettings.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"profiles": {
|
||||
"Windows Machine": {
|
||||
"commandName": "MsixPackage",
|
||||
"nativeDebugging": false
|
||||
}
|
||||
}
|
||||
}
|
||||
4
Resources/AppIcon/appicon.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0" y="0" width="456" height="456" fill="#512BD4" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 228 B |
8
Resources/AppIcon/appiconfg.svg
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<path d="m 105.50037,281.60863 c -2.70293,0 -5.00091,-0.90042 -6.893127,-2.70209 -1.892214,-1.84778 -2.837901,-4.04181 -2.837901,-6.58209 0,-2.58722 0.945687,-4.80389 2.837901,-6.65167 1.892217,-1.84778 4.190197,-2.77167 6.893127,-2.77167 2.74819,0 5.06798,0.92389 6.96019,2.77167 1.93749,1.84778 2.90581,4.06445 2.90581,6.65167 0,2.54028 -0.96832,4.73431 -2.90581,6.58209 -1.89221,1.80167 -4.212,2.70209 -6.96019,2.70209 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="M 213.56111,280.08446 H 195.99044 L 149.69953,207.0544 c -1.17121,-1.84778 -2.14037,-3.76515 -2.90581,-5.75126 h -0.40578 c 0.36051,2.12528 0.54076,6.67515 0.54076,13.6496 v 65.13172 h -15.54349 v -99.36009 h 18.71925 l 44.7374,71.29798 c 1.89222,2.95695 3.1087,4.98917 3.64945,6.09751 h 0.26996 c -0.45021,-2.6325 -0.67573,-7.09015 -0.67573,-13.37293 v -64.02256 h 15.47557 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="m 289.25134,280.08446 h -54.40052 v -99.36009 h 52.23835 v 13.99669 h -36.15411 v 28.13085 h 33.31621 v 13.9271 h -33.31621 v 29.37835 h 38.31628 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="M 366.56466,194.72106 H 338.7222 v 85.3634 h -16.08423 v -85.3634 h -27.77455 v -13.99669 h 71.70124 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
BIN
Resources/Fonts/OpenSans-Regular.ttf
Normal file
BIN
Resources/Fonts/OpenSans-Semibold.ttf
Normal file
BIN
Resources/Images/add.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
Resources/Images/adda.png
Normal file
|
After Width: | Height: | Size: 429 B |
BIN
Resources/Images/delete.png
Normal file
|
After Width: | Height: | Size: 451 B |
BIN
Resources/Images/dotnet_bot.png
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
Resources/Images/pencil.png
Normal file
|
After Width: | Height: | Size: 801 B |
BIN
Resources/Images/upload.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
Resources/Images/verified.png
Normal file
|
After Width: | Height: | Size: 2 KiB |
BIN
Resources/Images/verifiednight.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
15
Resources/Raw/AboutAssets.txt
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
Any raw assets you want to be deployed with your application can be placed in
|
||||
this directory (and child directories). Deployment of the asset to your application
|
||||
is automatically handled by the following `MauiAsset` Build Action within your `.csproj`.
|
||||
|
||||
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
|
||||
|
||||
These files will be deployed with you package and will be accessible using Essentials:
|
||||
|
||||
async Task LoadMauiAsset()
|
||||
{
|
||||
using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt");
|
||||
using var reader = new StreamReader(stream);
|
||||
|
||||
var contents = reader.ReadToEnd();
|
||||
}
|
||||
8
Resources/Splash/splash.svg
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<path d="m 105.50037,281.60863 c -2.70293,0 -5.00091,-0.90042 -6.893127,-2.70209 -1.892214,-1.84778 -2.837901,-4.04181 -2.837901,-6.58209 0,-2.58722 0.945687,-4.80389 2.837901,-6.65167 1.892217,-1.84778 4.190197,-2.77167 6.893127,-2.77167 2.74819,0 5.06798,0.92389 6.96019,2.77167 1.93749,1.84778 2.90581,4.06445 2.90581,6.65167 0,2.54028 -0.96832,4.73431 -2.90581,6.58209 -1.89221,1.80167 -4.212,2.70209 -6.96019,2.70209 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="M 213.56111,280.08446 H 195.99044 L 149.69953,207.0544 c -1.17121,-1.84778 -2.14037,-3.76515 -2.90581,-5.75126 h -0.40578 c 0.36051,2.12528 0.54076,6.67515 0.54076,13.6496 v 65.13172 h -15.54349 v -99.36009 h 18.71925 l 44.7374,71.29798 c 1.89222,2.95695 3.1087,4.98917 3.64945,6.09751 h 0.26996 c -0.45021,-2.6325 -0.67573,-7.09015 -0.67573,-13.37293 v -64.02256 h 15.47557 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="m 289.25134,280.08446 h -54.40052 v -99.36009 h 52.23835 v 13.99669 h -36.15411 v 28.13085 h 33.31621 v 13.9271 h -33.31621 v 29.37835 h 38.31628 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
<path d="M 366.56466,194.72106 H 338.7222 v 85.3634 h -16.08423 v -85.3634 h -27.77455 v -13.99669 h 71.70124 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
45
Resources/Styles/Colors.xaml
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<?xaml-comp compile="true" ?>
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
|
||||
|
||||
<!-- Note: For Android please see also Platforms\Android\Resources\values\colors.xml -->
|
||||
|
||||
<Color x:Key="Primary">#512BD4</Color>
|
||||
<Color x:Key="PrimaryDark">#ac99ea</Color>
|
||||
<Color x:Key="PrimaryDarkText">#242424</Color>
|
||||
<Color x:Key="Secondary">#DFD8F7</Color>
|
||||
<Color x:Key="SecondaryDarkText">#9880e5</Color>
|
||||
<Color x:Key="Tertiary">#2B0B98</Color>
|
||||
|
||||
<Color x:Key="White">White</Color>
|
||||
<Color x:Key="Black">Black</Color>
|
||||
<Color x:Key="Magenta">#D600AA</Color>
|
||||
<Color x:Key="MidnightBlue">#190649</Color>
|
||||
<Color x:Key="OffBlack">#1f1f1f</Color>
|
||||
|
||||
<Color x:Key="Gray100">#E1E1E1</Color>
|
||||
<Color x:Key="Gray200">#C8C8C8</Color>
|
||||
<Color x:Key="Gray300">#ACACAC</Color>
|
||||
<Color x:Key="Gray400">#919191</Color>
|
||||
<Color x:Key="Gray500">#6E6E6E</Color>
|
||||
<Color x:Key="Gray600">#404040</Color>
|
||||
<Color x:Key="Gray900">#212121</Color>
|
||||
<Color x:Key="Gray950">#141414</Color>
|
||||
|
||||
<SolidColorBrush x:Key="PrimaryBrush" Color="{StaticResource Primary}"/>
|
||||
<SolidColorBrush x:Key="SecondaryBrush" Color="{StaticResource Secondary}"/>
|
||||
<SolidColorBrush x:Key="TertiaryBrush" Color="{StaticResource Tertiary}"/>
|
||||
<SolidColorBrush x:Key="WhiteBrush" Color="{StaticResource White}"/>
|
||||
<SolidColorBrush x:Key="BlackBrush" Color="{StaticResource Black}"/>
|
||||
|
||||
<SolidColorBrush x:Key="Gray100Brush" Color="{StaticResource Gray100}"/>
|
||||
<SolidColorBrush x:Key="Gray200Brush" Color="{StaticResource Gray200}"/>
|
||||
<SolidColorBrush x:Key="Gray300Brush" Color="{StaticResource Gray300}"/>
|
||||
<SolidColorBrush x:Key="Gray400Brush" Color="{StaticResource Gray400}"/>
|
||||
<SolidColorBrush x:Key="Gray500Brush" Color="{StaticResource Gray500}"/>
|
||||
<SolidColorBrush x:Key="Gray600Brush" Color="{StaticResource Gray600}"/>
|
||||
<SolidColorBrush x:Key="Gray900Brush" Color="{StaticResource Gray900}"/>
|
||||
<SolidColorBrush x:Key="Gray950Brush" Color="{StaticResource Gray950}"/>
|
||||
</ResourceDictionary>
|
||||
426
Resources/Styles/Styles.xaml
Normal file
|
|
@ -0,0 +1,426 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<?xaml-comp compile="true" ?>
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
|
||||
|
||||
<Style TargetType="ActivityIndicator">
|
||||
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="IndicatorView">
|
||||
<Setter Property="IndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}"/>
|
||||
<Setter Property="SelectedIndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray100}}"/>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="Stroke" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||
<Setter Property="StrokeShape" Value="Rectangle"/>
|
||||
<Setter Property="StrokeThickness" Value="1"/>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="BoxView">
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource PrimaryDarkText}}" />
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource PrimaryDark}}" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="BorderWidth" Value="0"/>
|
||||
<Setter Property="CornerRadius" Value="8"/>
|
||||
<Setter Property="Padding" Value="14,10"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="PointerOver" />
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="CheckBox">
|
||||
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="DatePicker">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Editor">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Entry">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Frame">
|
||||
<Setter Property="HasShadow" Value="False" />
|
||||
<Setter Property="BorderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
|
||||
<Setter Property="CornerRadius" Value="8" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="ImageButton">
|
||||
<Setter Property="Opacity" Value="1" />
|
||||
<Setter Property="BorderColor" Value="Transparent"/>
|
||||
<Setter Property="BorderWidth" Value="0"/>
|
||||
<Setter Property="CornerRadius" Value="0"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="Opacity" Value="0.5" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="PointerOver" />
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Label">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Span">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Label" x:Key="Headline">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource White}}" />
|
||||
<Setter Property="FontSize" Value="32" />
|
||||
<Setter Property="HorizontalOptions" Value="Center" />
|
||||
<Setter Property="HorizontalTextAlignment" Value="Center" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Label" x:Key="SubHeadline">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource White}}" />
|
||||
<Setter Property="FontSize" Value="24" />
|
||||
<Setter Property="HorizontalOptions" Value="Center" />
|
||||
<Setter Property="HorizontalTextAlignment" Value="Center" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="ListView">
|
||||
<Setter Property="SeparatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||
<Setter Property="RefreshControlColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Picker">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="ProgressBar">
|
||||
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="RadioButton">
|
||||
<Setter Property="BackgroundColor" Value="Transparent"/>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="RefreshView">
|
||||
<Setter Property="RefreshColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="SearchBar">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" />
|
||||
<Setter Property="CancelButtonColor" Value="{StaticResource Gray500}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="SearchHandler">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Shadow">
|
||||
<Setter Property="Radius" Value="15" />
|
||||
<Setter Property="Opacity" Value="0.5" />
|
||||
<Setter Property="Brush" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}" />
|
||||
<Setter Property="Offset" Value="10,10" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Slider">
|
||||
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
|
||||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
|
||||
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
|
||||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="SwipeItem">
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Switch">
|
||||
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
<Setter Property="ThumbColor" Value="{StaticResource White}" />
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="On">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Secondary}, Dark={StaticResource Gray200}}" />
|
||||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Off">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="TimePicker">
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||
<Setter Property="BackgroundColor" Value="Transparent"/>
|
||||
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||
<VisualStateGroupList>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateGroupList>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Page" ApplyToDerivedTypes="True">
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Shell" ApplyToDerivedTypes="True">
|
||||
<Setter Property="Shell.BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" />
|
||||
<Setter Property="Shell.ForegroundColor" Value="{OnPlatform WinUI={StaticResource Primary}, Default={StaticResource White}}" />
|
||||
<Setter Property="Shell.TitleColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource SecondaryDarkText}}" />
|
||||
<Setter Property="Shell.DisabledColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
|
||||
<Setter Property="Shell.UnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray200}}" />
|
||||
<Setter Property="Shell.NavBarHasShadow" Value="False" />
|
||||
<Setter Property="Shell.TabBarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
|
||||
<Setter Property="Shell.TabBarForegroundColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" />
|
||||
<Setter Property="Shell.TabBarTitleColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" />
|
||||
<Setter Property="Shell.TabBarUnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="NavigationPage">
|
||||
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" />
|
||||
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" />
|
||||
<Setter Property="IconColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="TabbedPage">
|
||||
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Gray950}}" />
|
||||
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" />
|
||||
<Setter Property="UnselectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
|
||||
<Setter Property="SelectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||