Finish Playlists databinding development
continuous-integration/drone/push Build is failing Details

pull/25/head
Corentin LEMAIRE 2 years ago
parent 3beaf2a7af
commit 0190bc4565

@ -13,7 +13,6 @@ public partial class App : Application
public App()
{
InitializeComponent();
MainPage = new AppShell();
}

@ -1,29 +1,29 @@
namespace Linaris;
public partial class Layout : ContentView
{
public Layout()
{
InitializeComponent();
}
namespace Linaris;
public partial class Layout : ContentView
{
public Layout()
{
InitializeComponent();
}
private async void Go_Home(object sender, EventArgs e)
{
await Navigation.PushAsync(new MainPage());
}
}
private async void Go_Playlists(object sender, EventArgs e)
{
await Navigation.PushAsync(new PlaylistsPage());
}
}
private async void Go_Back(object sender, EventArgs e)
{
await Navigation.PopAsync();
}
}
private async void Go_Files(object sender, EventArgs e)
{
await Navigation.PushAsync(new LocalFilesPage());
}
}
}

@ -1,7 +1,7 @@
<?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"
xmlns:local="clr-namespace:Linaris"
xmlns:local="clr-namespace:Linaris"
xmlns:model="clr-namespace:Model;assembly=Model"
xmlns:converters="clr-namespace:Linaris.Converters"
x:Class="Linaris.LocalFilesPage"
@ -24,7 +24,7 @@
<VerticalStackLayout Margin="10" Grid.ColumnSpan="2">
<Image Source="{Binding ImageURL}" Aspect="Fill" HorizontalOptions="Center" VerticalOptions="Center" HeightRequest="150" WidthRequest="150" IsAnimationPlaying="True" InputTransparent="False">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="ShowSubMenu" Command="{Binding ShowSubMenu}"/>
<TapGestureRecognizer Tapped="ShowSubMenu"/>
</Image.GestureRecognizers>
</Image>
<Label Text="{Binding Name}" Style="{StaticResource Titre}" IsVisible="{Binding IsRenaming, Converter={StaticResource InverseBooleanConverter}}" HorizontalTextAlignment="Center" WidthRequest="250" LineBreakMode="TailTruncation"/>

@ -159,9 +159,9 @@ namespace Linaris
void ShowSubMenu(object sender, EventArgs e)
{
if (sender is Image button)
if (sender is Image image)
{
if (button.BindingContext is CustomTitle customTitle)
if (image.BindingContext is CustomTitle customTitle)
{
if (!customTitle.IsSubMenuVisible)
{

@ -2,74 +2,56 @@
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Linaris"
xmlns:model="clr-namespace:Model;assembly=Model"
xmlns:converters="clr-namespace:Linaris.Converters"
x:Class="Linaris.PlaylistsPage"
Title="PlaylistsPage"
Style="{StaticResource PageFlyoutTrigger}">
<Grid Style="{StaticResource GridFlyoutTrigger}">
<Grid.RowDefinitions>
<RowDefinition Height="8*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ContentPage.Resources>
<converters:InverseBooleanConverter x:Key="InverseBooleanConverter" />
</ContentPage.Resources>
<Grid Style="{StaticResource GridFlyoutTrigger}" RowDefinitions="8*,*">
<local:Layout Grid.Column="0"/>
<ScrollView Grid.Column="1" BackgroundColor="#404040">
<ScrollView Grid.Column="1" Grid.Row="0" BackgroundColor="#404040">
<VerticalStackLayout>
<SearchBar Style="{StaticResource SearchBar}"/>
<FlexLayout Direction="Row" AlignItems="Start" JustifyContent="SpaceAround" Wrap="Wrap">
<VerticalStackLayout Margin="10">
<ImageButton Source="playlist.jpg" SemanticProperties.Description="Playlist 1980's" Style="{StaticResource Pochette}"/>
<Label Text="1980's" Style="{StaticResource Titre}"></Label>
</VerticalStackLayout>
<VerticalStackLayout Margin="10">
<ImageButton Source="playlist1.png" SemanticProperties.Description="Playlist 1990's" Style="{StaticResource Pochette}"/>
<Label Text="1990's" Style="{StaticResource Titre}"></Label>
</VerticalStackLayout>
<VerticalStackLayout Margin="10">
<ImageButton Source="playlist2.jpg" SemanticProperties.Description="Playlist 2000's" Style="{StaticResource Pochette}"/>
<Label Text="2000's" Style="{StaticResource Titre}"></Label>
</VerticalStackLayout>
<VerticalStackLayout Margin="10">
<ImageButton Source="playlist3.jpg" SemanticProperties.Description="Playlist 2010's" Style="{StaticResource Pochette}"/>
<Label Text="2010's" Style="{StaticResource Titre}"></Label>
</VerticalStackLayout>
<VerticalStackLayout Margin="10">
<ImageButton Source="playlist4.png" SemanticProperties.Description="Playlist 2020" Style="{StaticResource Pochette}"/>
<Label Text="2020" Style="{StaticResource Titre}"></Label>
</VerticalStackLayout>
<VerticalStackLayout Margin="10">
<ImageButton Source="playlist5.jpg" SemanticProperties.Description="Playlist 2021" Style="{StaticResource Pochette}"/>
<Label Text="2021" Style="{StaticResource Titre}"></Label>
</VerticalStackLayout>
<VerticalStackLayout Margin="10">
<ImageButton Source="playlist6.png" SemanticProperties.Description="Playlist 2022" Style="{StaticResource Pochette}"/>
<Label Text="2022" Style="{StaticResource Titre}"></Label>
</VerticalStackLayout>
<VerticalStackLayout Margin="10">
<ImageButton Source="playlist7.png" SemanticProperties.Description="Playlist 2023" Style="{StaticResource Pochette}"/>
<Label Text="2023" Style="{StaticResource Titre}"></Label>
</VerticalStackLayout>
<FlexLayout Direction="Row" AlignItems="Start" BindableLayout.ItemsSource="{Binding Playlists}" JustifyContent="SpaceAround" Wrap="Wrap">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Grid ColumnDefinitions="2*,*">
<VerticalStackLayout Margin="10" Grid.ColumnSpan="2">
<Image Source="{Binding ImageURL}" Aspect="Fill" HorizontalOptions="Center" VerticalOptions="Center" HeightRequest="150" WidthRequest="150" IsAnimationPlaying="True" InputTransparent="False">
<Image.GestureRecognizers>
<TapGestureRecognizer Tapped="ShowSubMenu"/>
</Image.GestureRecognizers>
</Image>
<Label Text="{Binding Name}" Style="{StaticResource Titre}" IsVisible="{Binding IsRenaming, Converter={StaticResource InverseBooleanConverter}}" HorizontalTextAlignment="Center" WidthRequest="250" LineBreakMode="TailTruncation"/>
<Entry TextChanged="CheckNewName" Text="{Binding NewName}" Placeholder="Nouveau nom" IsVisible="{Binding IsRenaming}" Completed="RenamePlaylist"/>
</VerticalStackLayout>
<Grid Grid.ColumnSpan="2" BackgroundColor="Grey" HeightRequest="125" WidthRequest="155" RowDefinitions="*,*,*,*" IsVisible="{Binding IsSubMenuVisible}">
<Button Grid.Row="0" Text="Accéder à la playlist" Clicked="GoToPlaylist"/>
<Button Grid.Row="1" Text="Supprimer" Clicked="RemovePlaylist"/>
<Button Grid.Row="2" Text="Renommer" Clicked="RenamePlaylist"/>
<Button Grid.Row="3" Text="Changer l'image" Clicked="ChangeImage"/>
</Grid>
<Grid.GestureRecognizers>
<TapGestureRecognizer />
</Grid.GestureRecognizers>
</Grid>
</DataTemplate>
</BindableLayout.ItemTemplate>
</FlexLayout>
<Button WidthRequest="300" HeightRequest="50" Margin="0,20,0,20" BackgroundColor="{StaticResource Primary}" Text="Ajouter d'autres playlists" Clicked="ShowEntryPlaylist"/>
<Entry WidthRequest="300" HeightRequest="50" Margin="0,20,0,20" BackgroundColor="DimGrey" Text="" Placeholder="Nom de la nouvelle playlist" Completed="CreatePlaylist" IsVisible="{Binding IsNewPlaylist}"/>
</VerticalStackLayout>
</ScrollView>
<local:FooterPage Grid.Row="1" Grid.ColumnSpan="2"/>
<Grid.GestureRecognizers>
<TapGestureRecognizer Tapped="ResetAll"/>
</Grid.GestureRecognizers>
</Grid>
</ContentPage>

@ -1,9 +1,236 @@
using Model;
using Model.Stub;
using System.Collections.ObjectModel;
namespace Linaris;
public partial class PlaylistsPage : ContentPage
{
public PlaylistsPage()
private ObservableCollection<Playlist> playlists = App.Manager.GetPlaylists();
public ObservableCollection<Playlist> Playlists
{
get => playlists;
}
private bool isNewPlaylist = false;
public bool IsNewPlaylist
{
get => isNewPlaylist;
set
{
isNewPlaylist = value;
OnPropertyChanged(nameof(IsNewPlaylist));
}
}
public PlaylistsPage()
{
InitializeComponent();
}
BindingContext = this;
}
// Reset methods
void ResetAll(object sender, EventArgs e)
{
ResetSubMenus(sender, e);
ResetRenaming(sender, e);
IsNewPlaylist = false;
}
void ResetSubMenus(object sender, EventArgs e)
{
foreach (var Playlist in playlists)
{
Playlist.IsSubMenuVisible = false;
}
}
void ResetRenaming(object sender, EventArgs e)
{
foreach (var Playlist in playlists)
{
Playlist.IsRenaming = false;
if (!CheckRenaming(Playlist))
{
Playlist.NewName = Playlist.Name;
}
else
{
Playlist.Name = Playlist.NewName;
}
}
}
// Add methods
void CreatePlaylist(object sender, EventArgs e)
{
if (sender is Entry entry)
{
if (!HasSameName(entry.Text))
{
Playlist playlist = new Playlist(entry.Text, "", "none.png");
App.Manager.AddPlaylist(playlist);
playlists.Add(playlist);
IsNewPlaylist = false;
}
}
}
// Remove methods
void RemovePlaylist(object sender, EventArgs e)
{
if (sender is Button button)
{
if (button.BindingContext is Playlist playlist)
{
App.Manager.RemovePlaylist(playlist);
playlists.Remove(playlist);
}
}
}
// Show methods
void ShowSubMenu(object sender, EventArgs e)
{
if (sender is Image image)
{
if (image.BindingContext is Playlist playlist)
{
if (!playlist.IsSubMenuVisible)
{
ResetAll(sender, e);
playlist.IsSubMenuVisible = true;
}
else
{
ResetSubMenus(sender, e);
}
}
}
}
void ShowEntryPlaylist(object sender, EventArgs e)
{
IsNewPlaylist = true;
}
// Change methods
void RenamePlaylist(object sender, EventArgs e)
{
ResetSubMenus(sender, e);
if (sender is Button button)
{
if (button.BindingContext is Playlist playlist)
{
if (!playlist.IsRenaming)
{
ResetRenaming(sender, e);
playlist.IsRenaming = true;
}
else
{
ResetRenaming(sender, e);
}
}
}
else if (sender is Entry entry)
{
if (entry.BindingContext is Playlist playlist)
{
if (!CheckRenaming(playlist))
{
entry.TextColor = Color.FromRgb(255,0,0);
}
else
{
ResetRenaming(sender, e);
playlist.Name = playlist.NewName;
}
}
}
}
private async void ChangeImage(object sender, EventArgs e)
{
var result = await FilePicker.PickAsync(new PickOptions
{
PickerTitle = "Choisissez une nouvelle image !",
FileTypes = FilePickerFileType.Images
});
if (result == null)
{
return;
}
if (sender is Button button)
{
if (button.BindingContext is Playlist playlist)
{
playlist.ImageURL = result.FullPath;
}
}
}
// Search methods
bool HasSameName(string name)
{
foreach(Playlist playlist in playlists)
{
if (playlist.Name == name)
{
return true;
}
}
return false;
}
// Check methods
void CheckNewName(object sender, EventArgs e)
{
if (sender is Entry entry)
{
if (entry.BindingContext is Playlist playlist)
{
if (!CheckRenaming(playlist))
{
entry.TextColor = Color.FromRgb(255, 0, 0);
}
else
{
entry.TextColor = Color.FromRgb(255, 255, 255);
}
}
}
}
bool CheckRenaming(Playlist playlist)
{
if (playlist.NewName.Length > Manager.MAX_NAME_LENGTH || string.IsNullOrWhiteSpace(playlist.NewName) || HasSameName(playlist.NewName))
{
return false;
}
return true;
}
// Navigation
async void GoToPlaylist(object sender, EventArgs e)
{
await Navigation.PushAsync(new PlaylistPage());
}
}

@ -1,12 +1,19 @@
using Model.Stub;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Xml.Serialization;
namespace Model;
public class Playlist
public class Playlist : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
public string Name
{
get => name;
@ -17,11 +24,27 @@ public class Playlist
{
name = value;
}
OnPropertyChanged();
}
}
private string name = Manager.DEFAULT_NAME;
public string NewName
{
get => newName;
set
{
if (value != null && value.Length < Manager.MAX_NAME_LENGTH)
{
newName = value;
}
}
}
private string newName = Manager.DEFAULT_NAME;
public string Description
{
get => description;
@ -32,6 +55,7 @@ public class Playlist
{
description = value;
}
OnPropertyChanged();
}
}
@ -43,9 +67,14 @@ public class Playlist
{
return titles;
}
private set
{
titles = value;
OnPropertyChanged();
}
}
private readonly ObservableCollection<CustomTitle> titles = new ObservableCollection<CustomTitle>();
private ObservableCollection<CustomTitle> titles = new ObservableCollection<CustomTitle>();
public string ImageURL
{
@ -58,14 +87,11 @@ public class Playlist
value = "none.png";
imageURL = value;
}
if (value.Contains(' '))
{
imageURL = value.Replace(' ', '_');
}
else if (value.Contains('.'))
{
imageURL = value;
}
OnPropertyChanged();
}
}
@ -106,9 +132,40 @@ public class Playlist
}
}
public bool IsSubMenuVisible
{
get => isSubMenuVisible;
set
{
if (isSubMenuVisible != value)
{
isSubMenuVisible = value;
}
OnPropertyChanged(nameof(IsSubMenuVisible));
}
}
private bool isSubMenuVisible;
public bool IsRenaming
{
get => isRenaming;
set
{
if (isRenaming != value)
{
isRenaming = value;
}
OnPropertyChanged();
}
}
private bool isRenaming = false;
public Playlist(string nom, string description, string imageURL)
{
Name = nom;
NewName = nom;
Description = description;
ImageURL = imageURL;
}

Loading…
Cancel
Save