Skip to content

Commit

Permalink
Merge pull request #182 from LiamMorrow/auto-screenshots
Browse files Browse the repository at this point in the history
  • Loading branch information
LiamMorrow authored Jun 29, 2024
2 parents 6d81acc + 562d180 commit b71eb7e
Show file tree
Hide file tree
Showing 41 changed files with 717 additions and 59 deletions.
4 changes: 4 additions & 0 deletions LiftLog.App/MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ public static MauiApp CreateMauiApp()
#if DEBUG
builder.Services.AddBlazorWebViewDeveloperTools();
builder.Logging.AddDebug();
builder.Services.AddSingleton<
Ui.Pages.Screenshot.IScreenshotStatsImportsProvider,
AppScreenshotStatsImportsProvider
>();
#endif
// Add this section anywhere on the builder:
builder.Logging.AddSentry(options =>
Expand Down
11 changes: 11 additions & 0 deletions LiftLog.App/Services/AppDataFileStorageKeyValueStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ public async ValueTask SetItemAsync(string key, byte[] value)
await File.WriteAllBytesAsync(GetFileName(key), value);
}

public ValueTask RemoveItemAsync(string key)
{
var fileName = GetFileName(key);
var exists = File.Exists(fileName);
if (exists)
{
File.Delete(fileName);
}
return ValueTask.CompletedTask;
}

private string GetFileName(string key)
{
var dataDir = FileSystem.Current.AppDataDirectory;
Expand Down
17 changes: 17 additions & 0 deletions LiftLog.App/Services/AppScreenshotStatsImportsProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#if DEBUG
using LiftLog.Ui.Pages.Screenshot;

namespace LiftLog.App.Services;

public class AppScreenshotStatsImportsProvider : IScreenshotStatsImportsProvider
{
public async Task<Stream> GetImportBytesAsync()
{
var result = await FileSystem.OpenAppPackageFileAsync(
"wwwroot/_content/LiftLog.Ui/export.liftlogbackup.gz"
);
return result;
}
}

#endif
10 changes: 8 additions & 2 deletions LiftLog.Lib/Models/ImmutableListValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,15 @@ public ImmutableListValue(List<T> items)

private int? _precomputedHashcode;

public int Count => ((IReadOnlyCollection<T>)Items).Count;
public int Count => Items.Count;

public T this[int index] => ((IReadOnlyList<T>)Items)[index];
public T this[int index] => Items[index];

public ImmutableListValue<T> this[Range range] =>
Items.GetRange(
range.GetOffsetAndLength(Count).Offset,
range.GetOffsetAndLength(Count).Length
);

public static implicit operator ImmutableListValue<T>(ImmutableList<T> source)
{
Expand Down
2 changes: 2 additions & 0 deletions LiftLog.Ui/LiftLog.Ui.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
<Content Remove="wwwroot\load-tailwind.js"/>
<Content Remove="wwwroot\tailwind.js"/>
<Content Remove="wwwroot\twconf.json"/>
<Content Remove="wwwroot\export.liftlogbackup.gz"/>
<Content Remove="Pages\Screenshot\ScreenshotCollectorPage.razor"/>
</ItemGroup>

<ItemGroup>
Expand Down
1 change: 1 addition & 0 deletions LiftLog.Ui/Pages/History/HistoryEditPage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
@using LiftLog.Ui.Store.App
@using LiftLog.Ui.Store.Program
@using Fluxor;

@inherits Fluxor.Blazor.Web.Components.FluxorComponent

@inject IState<CurrentSessionState> CurrentSessionState
Expand Down
16 changes: 16 additions & 0 deletions LiftLog.Ui/Pages/Screenshot/ScreenshotCollectorPage.Ai.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#if DEBUG
using LiftLog.Lib.Models;
using LiftLog.Ui.Store.App;
using LiftLog.Ui.Store.CurrentSession;

namespace LiftLog.Ui.Pages.Screenshot;

public partial class ScreenshotCollectorPage
{
private async Task HandleAiPageScreenshotCollection()
{
Dispatcher.Dispatch(new NavigateAction("/settings/ai-planner"));
await Task.Yield();
}
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#if DEBUG
using LiftLog.Lib.Models;
using LiftLog.Ui.Store.App;
using LiftLog.Ui.Store.CurrentSession;
using LiftLog.Ui.Store.Program;

namespace LiftLog.Ui.Pages.Screenshot;

public partial class ScreenshotCollectorPage
{
private async Task HandleExerciseEditorScreenshotCollection()
{
Dispatcher.Dispatch(
new SetProgramSessionsAction(ProgramState.Value.ActivePlanId, [demoSessionBlueprint])
);
Dispatcher.Dispatch(
new NavigateAction(
$"/settings/manage-workouts/manage-session/0?editingExercise=0&planId={ProgramState.Value.ActivePlanId}"
)
);
await Task.Yield();
}
}
#endif
59 changes: 59 additions & 0 deletions LiftLog.Ui/Pages/Screenshot/ScreenshotCollectorPage.Home.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#if DEBUG
using LiftLog.Lib.Models;
using LiftLog.Ui.Services;
using LiftLog.Ui.Store.App;
using LiftLog.Ui.Store.CurrentSession;
using LiftLog.Ui.Store.Program;

namespace LiftLog.Ui.Pages.Screenshot;

public partial class ScreenshotCollectorPage
{
private SessionBlueprint demoSessionBlueprint =
new(
Name: "Session 1",
Exercises:
[
new ExerciseBlueprint(
Name: "Squat",
Sets: 3,
RepsPerSet: 10,
WeightIncreaseOnSuccess: 2.5m,
RestBetweenSets: Rest.Medium,
SupersetWithNext: false
),
new ExerciseBlueprint(
Name: "Bench Press",
Sets: 3,
RepsPerSet: 10,
WeightIncreaseOnSuccess: 2.5m,
RestBetweenSets: Rest.Medium,
SupersetWithNext: false
),
new ExerciseBlueprint(
Name: "Deadlift",
Sets: 3,
RepsPerSet: 10,
WeightIncreaseOnSuccess: 2.5m,
RestBetweenSets: Rest.Medium,
SupersetWithNext: false
)
]
);

private async Task HandleHomeScreenshotCollection()
{
var builtInProgram = BuiltInProgramService.BuiltInPrograms.First();
Dispatcher.Dispatch(new SetCurrentSessionAction(SessionTarget.WorkoutSession, null));
Dispatcher.Dispatch(new SetActiveProgramAction(builtInProgram.Key));
Dispatcher.Dispatch(
new SetProgramSessionsAction(
ProgramState.Value.ActivePlanId,
builtInProgram.Value.Sessions
)
);
Dispatcher.Dispatch(new NavigateAction($"/"));
await Task.Yield();
}
}
#endif
50 changes: 50 additions & 0 deletions LiftLog.Ui/Pages/Screenshot/ScreenshotCollectorPage.Stats.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#if DEBUG
using System.IO.Compression;
using LiftLog.Lib.Models;
using LiftLog.Ui.Store.App;
using LiftLog.Ui.Store.CurrentSession;
using LiftLog.Ui.Store.Settings;
using LiftLog.Ui.Store.Stats;
using Microsoft.AspNetCore.Components;

namespace LiftLog.Ui.Pages.Screenshot;

public partial class ScreenshotCollectorPage
{
[Inject]
public HttpClient HttpClient { get; set; } = null!;

[Inject]
public IScreenshotStatsImportsProvider ScreenshotStatsImportsProvider { get; set; } = null!;

private async Task HandleStatsScreenshotCollection()
{
var imported = await ScreenshotStatsImportsProvider.GetImportBytesAsync();
using GZipStream gzip = new(imported, CompressionMode.Decompress);
using MemoryStream memoryStream = new();
await gzip.CopyToAsync(memoryStream);
var bytes = memoryStream.ToArray();
Dispatcher.Dispatch(new ImportDataBytesAction(bytes));
var latestSession = await ProgressRepository.GetOrderedSessions().FirstAsync();
var dateDiffToNow = (
DateTime.Now - latestSession.Date.ToDateTime(TimeOnly.FromDateTime(DateTime.Now))
).Days;

var remappedToTodaySessions = await ProgressRepository
.GetOrderedSessions()
.Select(session => session with { Date = session.Date.AddDays(dateDiffToNow) })
.ToListAsync();

await ProgressRepository.SaveCompletedSessionsAsync(remappedToTodaySessions);

Dispatcher.Dispatch(new SetPinnedExerciseStatsAction([new("Bench Press")]));
Dispatcher.Dispatch(new SetShowBodyweightAction(false));
Dispatcher.Dispatch(new NavigateAction("/stats"));
}
}

public interface IScreenshotStatsImportsProvider
{
Task<Stream> GetImportBytesAsync();
}
#endif
23 changes: 23 additions & 0 deletions LiftLog.Ui/Pages/Screenshot/ScreenshotCollectorPage.WorkoutPage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#if DEBUG
using LiftLog.Lib.Models;
using LiftLog.Ui.Store.App;
using LiftLog.Ui.Store.CurrentSession;

namespace LiftLog.Ui.Pages.Screenshot;

public partial class ScreenshotCollectorPage
{
private async Task HandleWorkoutPageScreenshotCollection()
{
var demoSession = demoSessionBlueprint.GetEmptySession();
Dispatcher.Dispatch(new SetCurrentSessionAction(SessionTarget.WorkoutSession, demoSession));
Dispatcher.Dispatch(new UpdateExerciseWeightAction(SessionTarget.WorkoutSession, 0, 100));
Dispatcher.Dispatch(new UpdateExerciseWeightAction(SessionTarget.WorkoutSession, 1, 60));
Dispatcher.Dispatch(new UpdateExerciseWeightAction(SessionTarget.WorkoutSession, 2, 120));
Dispatcher.Dispatch(new UpdateBodyweightAction(SessionTarget.WorkoutSession, 85));
Dispatcher.Dispatch(new CycleExerciseRepsAction(SessionTarget.WorkoutSession, 0, 0));
Dispatcher.Dispatch(new NavigateAction("/session"));
await Task.Yield();
}
}
#endif
1 change: 1 addition & 0 deletions LiftLog.Ui/Pages/Screenshot/ScreenshotCollectorPage.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@page "/screenshot-collection"
61 changes: 61 additions & 0 deletions LiftLog.Ui/Pages/Screenshot/ScreenshotCollectorPage.razor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#if DEBUG
using Fluxor;
using LiftLog.Ui.Services;
using LiftLog.Ui.Store.Program;
using LiftLog.Ui.Store.Settings;
using Microsoft.AspNetCore.Components;

namespace LiftLog.Ui.Pages.Screenshot;

public partial class ScreenshotCollectorPage : ComponentBase
{
[Inject]
public IDispatcher Dispatcher { get; set; } = null!;

[Inject]
public ProgressRepository ProgressRepository { get; set; } = null!;

[Inject]
public IState<ProgramState> ProgramState { get; set; } = null!;

[Parameter]
[SupplyParameterFromQuery(Name = "type")]
public string ScreenshotCollectionType { get; set; } = "";

protected override async Task OnInitializedAsync()
{
await ProgressRepository.ClearAsync();
Dispatcher.Dispatch(new SetProgramSessionsAction(ProgramState.Value.ActivePlanId, []));
Dispatcher.Dispatch(new SetUseImperialUnitsAction(false));
Dispatcher.Dispatch(new SetShowBodyweightAction(true));
Dispatcher.Dispatch(new SetShowFeedAction(true));
Dispatcher.Dispatch(new SetShowTipsAction(false));
Dispatcher.Dispatch(
new SetThemeAction(
uint.Parse("00AA00", System.Globalization.NumberStyles.HexNumber),
ThemePreference.Light
)
);

switch (ScreenshotCollectionType.ToLower())
{
case "workoutpage":
await HandleWorkoutPageScreenshotCollection();
break;
case "home":
await HandleHomeScreenshotCollection();
break;
case "exerciseeditor":
await HandleExerciseEditorScreenshotCollection();
break;
case "stats":
await HandleStatsScreenshotCollection();
break;
case "ai":
await HandleAiPageScreenshotCollection();
break;
}
await base.OnInitializedAsync();
}
}
#endif
1 change: 1 addition & 0 deletions LiftLog.Ui/Pages/Settings/AiSessionCreatorPage.razor
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@page "/settings/ai-session-creator"
@inherits Fluxor.Blazor.Web.Components.FluxorComponent

@using LiftLog.Lib.Services;

@inject NavigationManager NavigationManager
Expand Down
11 changes: 10 additions & 1 deletion LiftLog.Ui/Pages/Settings/ManageSessionPage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@


@code {

[Parameter][SupplyParameterFromQuery(Name="editingExercise")] public int? EditingExerciseIndexParam { get; set; }
[Parameter] public int SessionIndex { get; set; }

[SupplyParameterFromQuery(Name = "planId")]
Expand All @@ -73,6 +73,15 @@

private FullScreenDialog? editDialog;

protected override void OnAfterRender(bool firstRender)
{
if (firstRender && EditingExerciseIndexParam is not null && SessionEditorState is {Value: {SessionBlueprint: not null}})
{
BeginEditExercise(SessionEditorState.Value.SessionBlueprint.Exercises[EditingExerciseIndexParam.Value], EditingExerciseIndexParam.Value);
}
base.OnAfterRender(firstRender);
}


void MoveExerciseUp(ExerciseBlueprint exerciseBlueprint)
{
Expand Down
8 changes: 7 additions & 1 deletion LiftLog.Ui/Pages/StatsPage.razor
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ else if (!StatsState.Value.IsLoading && StatsState.Value.OverallView is not null
</SingleValueStatisticsCard>
</div>
<div class="flex flex-col gap-2">
@foreach(var pinnedStat in StatsState.Value.GetPinnedExercises().IndexedTuples())
{
<Card>
<StatGraphCardContent Title="@pinnedStat.Item.ExerciseName" Statistics="[pinnedStat.Item.Statistics, pinnedStat.Item.OneRepMaxStatistics]" RenderDelay="TimeSpan.FromMilliseconds(200 + pinnedStat.Index * 200)"/>
</Card>
}
@if (SettingsState.Value.ShowBodyweight && overallStats.BodyweightStats.Statistics.Any())
{
<Card class="mx-2">
Expand All @@ -70,7 +76,7 @@ else if (!StatsState.Value.IsLoading && StatsState.Value.OverallView is not null
<Card class="mx-2">
<StatGraphCardContent Title="Sessions" Statistics="overallStats.SessionStats" RenderDelay="TimeSpan.FromMilliseconds(200)"/>
</Card>
<CardList Items="@(overallStats.ExerciseStats.IndexedTuples())">
<CardList Items="@(overallStats.ExerciseStats.Where(x=>!StatsState.Value.IsExercisePinned(x)).IndexedTuples())">
<StatGraphCardContent Title="@context.Item.ExerciseName" Statistics="[context.Item.Statistics, context.Item.OneRepMaxStatistics]" RenderDelay="TimeSpan.FromMilliseconds(200 + context.Index * 200)"/>
</CardList>
</div>
Expand Down
3 changes: 3 additions & 0 deletions LiftLog.Ui/ServiceRegistration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ public static IServiceCollection RegisterUiServices<
#endif
);

services.AddScoped<CurrentProgramRepository>();
services.AddScoped<ProgressRepository>();
services.AddScoped<PreferencesRepository>();
services.AddSingleton<NavigationManagerProvider>();

services.AddSingleton<CurrentProgramRepository>();
Expand Down
1 change: 1 addition & 0 deletions LiftLog.Ui/Services/IKeyValueStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ public interface IKeyValueStore
{
ValueTask<string?> GetItemAsync(string key);
ValueTask<byte[]?> GetItemBytesAsync(string key);
ValueTask RemoveItemAsync(string key);
ValueTask SetItemAsync(string key, string value);
ValueTask SetItemAsync(string key, byte[] value);
}
Loading

0 comments on commit b71eb7e

Please sign in to comment.