Skip to content

Commit

Permalink
Add score editing feature
Browse files Browse the repository at this point in the history
  • Loading branch information
aetherstrata committed Feb 18, 2024
1 parent 2dff19f commit f88a7d7
Show file tree
Hide file tree
Showing 10 changed files with 190 additions and 50 deletions.
9 changes: 3 additions & 6 deletions Aosta.Ava/Aosta.Ava.Android/AndroidLauncher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,11 @@ public Task<bool> LaunchUriAsync(Uri uri)
{
ArgumentNullException.ThrowIfNull(uri);

if (uri.IsAbsoluteUri && context.PackageManager is { } packageManager)
if (uri.IsAbsoluteUri)
{
var intent = new Intent(Intent.ActionView, AndroidUri.Parse(uri.OriginalString));
if (intent.ResolveActivity(packageManager) is not null)
{
intent.SetFlags(flags);
context.StartActivity(intent);
}
intent.SetFlags(flags);
context.StartActivity(intent);
}

return Task.FromResult(false);
Expand Down
5 changes: 5 additions & 0 deletions Aosta.Ava/Aosta.Ava/Assets/Localization/en-US.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
{
"App.Version": "Version {0}",

"AnimeDetails.Menu.OpenOnMAL": "Open on MyAnimeList",
"AnimeDetails.Menu.Remove": "Remove from list",
"AnimeDetails.Score.PopupTitle": "Score",
"AnimeDetails.Score.Watermark": "Rate this anime",
"AnimeDetails.ToolTip.AddToRealm": "Add this anime to your watchlist",

"AnimeList.Header.NoAnime" : "The list is empty",
Expand Down Expand Up @@ -37,6 +40,7 @@
"Theme.Light": "Light",

"Label.All": "All",
"Label.CloseButton": "Cancel",
"Label.ContentType": "Type",
"Label.Date": "Date",
"Label.Episode.Number": "Episode #{0}",
Expand All @@ -47,6 +51,7 @@
"Label.NotAvailable.Long" : "Not available",
"Label.NotAvailable.Short" : "N/A",
"Label.Online": "Online",
"Label.PrimaryButton": "OK",
"Label.Recap": "Recap",
"Label.Score": "Score",
"Label.Season": "Season",
Expand Down
5 changes: 5 additions & 0 deletions Aosta.Ava/Aosta.Ava/Assets/Localization/it-IT.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
{
"App.Version": "Versione {0}",

"AnimeDetails.Menu.OpenOnMAL": "Apri su MyAnimeList",
"AnimeDetails.Menu.Remove": "Rimuovi dalla lista",
"AnimeDetails.Score.PopupTitle": "Voto",
"AnimeDetails.Score.Watermark": "Dai un voto a questo anime",
"AnimeDetails.ToolTip.AddToRealm": "Aggiungi questo anime alla tua lista",

"AnimeList.Header.NoAnime" : "La lista è vuota",
Expand Down Expand Up @@ -36,6 +39,7 @@
"Theme.Light": "Chiaro",

"Label.All": "Tutti",
"Label.CloseButton": "Annulla",
"Label.ContentType": "Tipo",
"Label.Date": "Data",
"Label.Episode.Number": "Episodio n.{0}",
Expand All @@ -46,6 +50,7 @@
"Label.NotAvailable.Long" : "Non disponibile",
"Label.NotAvailable.Short" : "N/D",
"Label.Online": "Online",
"Label.PrimaryButton": "OK",
"Label.Recap": "Recap",
"Label.Score": "Voto",
"Label.Season": "Stagione",
Expand Down
31 changes: 31 additions & 0 deletions Aosta.Ava/Aosta.Ava/Converters/ShortValueStringConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) Davide Pierotti <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using System.Globalization;

using Aosta.Ava.Localization;

using Avalonia.Data.Converters;
using Avalonia.Markup.Xaml;

namespace Aosta.Ava.Converters;

public class ShortValueStringConverter : MarkupExtension, IValueConverter
{
public override object ProvideValue(IServiceProvider serviceProvider) => this;

public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
return value switch
{
not null => value.ToString(),
null => LocalizedString.NA.Localized,
};
}

public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new InvalidOperationException($"The {nameof(ShortValueStringConverter)} converter shall only be used to convert objects to their string representation ");
}
}
3 changes: 1 addition & 2 deletions Aosta.Ava/Aosta.Ava/MainView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@
IconSource="List" />

<controls:CommandBarButton Command="{Binding GoHome}"
IconSource="Home"
IsDefault="True"/>
IconSource="Home"/>

<controls:CommandBarButton Command="{Binding GoSearch}"
IconSource="Find"/>
Expand Down
40 changes: 27 additions & 13 deletions Aosta.Ava/Aosta.Ava/Pages/LocalAnimeDetailsPage.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Aosta.Ava.Pages.LocalAnimeDetailsPage"
x:DataType="vm:LocalAnimeDetailsViewModel">
<UserControl.Styles>
<Style Selector="fluent|NumberBox">
<Setter Property="BorderThickness" Value="0"/>
</Style>
</UserControl.Styles>
<Grid RowDefinitions="Auto,*">
<local:TitleBar Grid.Row="0"
Title="{Binding DefaultTitle}">
Expand All @@ -20,9 +25,12 @@
<fluent:CommandBar ClosedDisplayMode="Minimal"
Height="48">
<fluent:CommandBar.SecondaryCommands>
<fluent:CommandBarButton Label="{localize:Localize AnimeDetails.Menu.OpenOnMAL}"
IconSource="Globe"
Command="{Binding OpenOnMal}" />
<fluent:CommandBarButton Label="{localize:Localize AnimeDetails.Menu.Remove}"
IconSource="Dismiss"
Command="{Binding RemoveFromRealm}" />
IconSource="Dismiss"
Command="{Binding RemoveFromRealm}" />
</fluent:CommandBar.SecondaryCommands>
</fluent:CommandBar>
</local:TitleBar.Menu>
Expand All @@ -49,23 +57,29 @@
<StackPanel Spacing="10">
<Border Background="{DynamicResource PureColorBackgroundBrush}"
HorizontalAlignment="Left"
Padding="5"
CornerRadius="5">
<StackPanel Orientation="Horizontal">
<fluent:FontIcon Glyph="{StaticResource StarGlyph}"
Margin="5,0"
FontFamily="{StaticResource SymbolThemeFontFamily}"
Foreground="Gold" />
<TextBlock Text="{Binding Score}" />
</StackPanel>
<Button Command="{Binding ShowScoreFlyout}"
Background="Transparent"
Padding="10"
BorderThickness="0">
<StackPanel Orientation="Horizontal"
Spacing="5">
<fluent:FontIcon Glyph="{StaticResource StarGlyph}"
FontFamily="{StaticResource SymbolThemeFontFamily}"
Foreground="Gold"
VerticalAlignment="Center"/>
<TextBlock Text="{Binding Anime.UserScore, Converter={converters:ShortValueStringConverter}}"
VerticalAlignment="Center"/>
</StackPanel>
</Button>
</Border>
<Border Background="{DynamicResource PureColorBackgroundBrush}"
HorizontalAlignment="Left"
Padding="5"
Padding="10"
CornerRadius="5">
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Horizontal"
Spacing="5">
<fluent:FontIcon Glyph="{StaticResource CalendarGlyph}"
Margin="5,0"
FontFamily="{StaticResource SymbolThemeFontFamily}" />
<ContentControl Content="{Binding Status}" />
</StackPanel>
Expand Down
4 changes: 4 additions & 0 deletions Aosta.Ava/Aosta.Ava/Pages/LocalAnimeDetailsPage.axaml.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
// Copyright (c) Davide Pierotti <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.

using System.Reactive.Linq;

using Aosta.Ava.ViewModels;

using Avalonia.Input;

namespace Aosta.Ava.Pages;

public partial class LocalAnimeDetailsPage : ReactivePageBase<LocalAnimeDetailsViewModel>
Expand Down
49 changes: 26 additions & 23 deletions Aosta.Ava/Aosta.Ava/Pages/LocalEpisodeDetailsPage.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,18 @@
IsVisible="{Binding Episode.Synopsis, Converter={converters:NullValueBoolConverter}}"
TextWrapping="WrapWithOverflow" />
<ContentControl Content="{Binding Duration}" />
<Button Theme="{StaticResource TransparentButton}"
Command="{Binding OpenMalUrl}">
<TextBlock Text="MyAnimeList"
Foreground="CornflowerBlue"
TextDecorations="Underline" />
</Button>
<StackPanel Orientation="Horizontal"
Spacing="10">
<TextBlock Text="{localize:Localize Label.ExternalLinks}"
FontSize="18"
FontWeight="Bold" />
<Button Theme="{StaticResource TransparentButton}"
Command="{Binding OpenMalUrl}">
<TextBlock Text="MyAnimeList"
Foreground="CornflowerBlue"
TextDecorations="Underline" />
</Button>
</StackPanel>
<StackPanel Orientation="Horizontal"
Spacing="10">
<TextBlock Text="{localize:Localize EpisodeDetails.Notes.Header}"
Expand All @@ -86,20 +92,17 @@
CornerRadius="10"
Background="{DynamicResource FloatingPaneBackgroundBrush}">
<StackPanel Spacing="5">
<Grid ColumnDefinitions="70, *">
<TextBlock Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Text="{Binding NewNoteTimeValue, Converter={converters:TimeStringConverter}}" />
<Slider Grid.Column="1"
Orientation="Horizontal"
Margin="0,0,10,0"
TickFrequency="1"
Minimum="0"
Maximum="{Binding Episode.Duration}"
Value="{Binding NewNoteTimeValue}"
IsVisible="{Binding Episode.Duration, Converter={converters:NullValueBoolConverter}}" />
</Grid>
<Slider ToolTip.VerticalOffset="10"
ToolTip.Placement="Top"
ToolTip.Tip="{Binding NewNoteTimeValue, Converter={converters:TimeStringConverter}}"
Orientation="Horizontal"
Margin="10,0"
TickFrequency="1"
Minimum="0"
Maximum="{Binding Episode.Duration}"
Value="{Binding NewNoteTimeValue}"
IsVisible="{Binding Episode.Duration, Converter={converters:NullValueBoolConverter}}">
</Slider>
<TextBox Watermark="{localize:Localize EpisodeDetails.Notes.TitleWatermark}"
Text="{Binding NewNoteTitle}"
MaxLines="1"
Expand Down Expand Up @@ -127,17 +130,17 @@
CommandParameter="{Binding}"
Background="Red">
<controls:FontIcon Glyph="{StaticResource DeleteGlyph}"
FontFamily="{StaticResource SymbolThemeFontFamily}"/>
FontFamily="{StaticResource SymbolThemeFontFamily}" />
</Button>
<TextBlock Grid.Row="0"
Grid.Column="0"
Text="{Binding PointInTime, Converter={converters:TimeStringConverter}}"/>
Text="{Binding PointInTime, Converter={converters:TimeStringConverter}}" />
<TextBlock Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="2"
Text="{Binding Title}"
FontWeight="Bold"
HorizontalAlignment="Center"/>
HorizontalAlignment="Center" />
<TextBlock Grid.Row="1"
Grid.Column="0"
Text="{Binding Note}" />
Expand Down
76 changes: 72 additions & 4 deletions Aosta.Ava/Aosta.Ava/ViewModels/LocalAnimeDetailsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,27 @@
using System.Reactive.Linq;
using System.Threading.Tasks;

using Aosta.Ava.Controls;
using Aosta.Ava.Extensions;
using Aosta.Ava.Localization;
using Aosta.Ava.ViewModels.DetailsPill;
using Aosta.Data;
using Aosta.Data.Extensions;
using Aosta.Data.Models;

using Avalonia.Controls;
using Avalonia.Controls.Templates;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.ReactiveUI;

using DynamicData;

using FluentAvalonia.UI.Controls;
using FluentAvalonia.UI.Controls.Primitives;

using ReactiveUI;
using ReactiveUI.Fody.Helpers;

using Splat;

Expand Down Expand Up @@ -57,6 +66,15 @@ internal LocalAnimeDetailsViewModel(IScreen host, Anime anime)

GoToEpisode = ReactiveCommand.CreateFromObservable((Episode episode) =>
HostScreen.Router.Navigate.Execute(new LocalEpisodeDetailsViewModel(HostScreen, episode, Anime)));

Anime.PropertyChanged += (_, args) =>
{
if (args.PropertyName == "watchStatus")
{
Status?.Dispose();
Status = Anime.WatchingStatus.Localize();
}
};
}

public IContentInfoPill DetailsPill { get; }
Expand All @@ -74,12 +92,62 @@ public string DefaultTitle
private readonly ReadOnlyObservableCollection<Episode> _episodes;
public ReadOnlyObservableCollection<Episode> Episodes => _episodes;

public string Score => Anime.UserScore?.ToString() ?? LocalizedString.NA;

public LocalizedString Status { get; }
[Reactive]
public LocalizedString? Status { get; set; }

public ReactiveCommand<Episode, IRoutableViewModel> GoToEpisode { get; }

public async Task OpenOnMal()
{
if (!string.IsNullOrEmpty(Anime.Url))
{
bool res = await Locator.Current.GetSafely<ILauncher>().LaunchUriAsync(new Uri(Anime.Url));
this.Log().Debug("Open url in browser: {Result}", res);
}
}

public async Task ShowScoreFlyout()
{
var numberBox = new NumberBox
{
HorizontalAlignment = HorizontalAlignment.Stretch,
Minimum = 0,
Maximum = 100,
Value = Anime.UserScore ?? 0,
SimpleNumberFormat = "F0",
PlaceholderText = Localizer.Instance["AnimeDetails.Score.Watermark"],
SpinButtonPlacementMode = NumberBoxSpinButtonPlacementMode.Inline,
ValidationMode = NumberBoxValidationMode.InvalidInputOverwritten,
TextAlignment = TextAlignment.Left
};

var okCommand = ReactiveCommand.Create(() =>
{
this.Log().Debug("Updated user score for {AnimeName}: {Score}", Anime.Titles.GetDefault().Title, Anime.UserScore);
_realm.Write(r =>
{
Anime.UserScore = (int)numberBox.Value;
});
});

var scoreFlyout = new ContentDialog
{
Title = Localizer.Instance["AnimeDetails.Score.PopupTitle"],
TitleTemplate = new FuncDataTemplate<string>((s, _) => new TextBlock
{
Text = s,
FontSize = 24,
FontWeight = FontWeight.Bold
}),
Content = numberBox,
PrimaryButtonText = Localizer.Instance["Label.PrimaryButton"],
PrimaryButtonCommand = okCommand,
CloseButtonText = Localizer.Instance["Label.CloseButton"]
};

await scoreFlyout.ShowAsync();
}

public void RemoveFromRealm()
{
_realm.Write(r => r.Remove(Anime));
Expand All @@ -89,7 +157,7 @@ public void RemoveFromRealm()
public void Dispose()
{
DetailsPill.Dispose();
Status.Dispose();
Status?.Dispose();
_episodesConnection.Dispose();
_subscriptionToken.Dispose();
}
Expand Down
Loading

0 comments on commit f88a7d7

Please sign in to comment.