F-Droid page: screenshots, a banner and a fuller description
Build / Desktop, server and tools (push) Successful in 1m5s
Build / Desktop, server and tools (push) Successful in 1m5s
The app's page in F-Droid had a stretched icon across the top, no pictures and two lines of text. It now shows six screenshots in English and Italian (the opening screen, what you can host, the path from the phone to the internet, one finding explained, a check under way and exactly what sharing would send), a banner, the icon at full size and a description of what the app checks and what stays on the phone. The screenshots are drawn from an invented connection, not the computer that makes them: documentation addresses, a made-up provider, nothing that belongs to anyone. One command redraws them after a change to the screens: dotnet run --project tools/Screenshots -- --store. The listing is in the layout Google Play uses, so the same files will serve there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W4YtEKqxKjKyHkFzuRVMNA
This commit is contained in:
1 parent
8c079e43c9
commit
5b2210a8a7
26 files changed
+214
-18
No files matched your search
@@ -1,3 +1,5 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Headless;
|
||||
@@ -10,18 +12,57 @@ using MeWeb.App.Services;
|
||||
using MeWeb.App.ViewModels;
|
||||
using MeWeb.App.Views;
|
||||
using MeWeb.Core.Checks;
|
||||
using MeWeb.Core.Knowledge;
|
||||
using MeWeb.Screenshots;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
var output = args.Length > 0 ? args[0] : Path.Combine("dist", "screenshots");
|
||||
var codes = args.Length > 1 ? args[1].Split(',', StringSplitOptions.RemoveEmptyEntries) : Languages.All.Select(l => l.Code).ToArray();
|
||||
var store = args.Length > 0 && args[0] == "--store";
|
||||
var output = store ? args.Length > 1 ? args[1] : Path.Combine("fastlane", "metadata", "android") : args.Length > 0 ? args[0] : Path.Combine("dist", "screenshots");
|
||||
var codes = !store && args.Length > 1 ? args[1].Split(',', StringSplitOptions.RemoveEmptyEntries) : Languages.All.Select(l => l.Code).ToArray();
|
||||
Directory.CreateDirectory(output);
|
||||
var data = Directory.CreateTempSubdirectory("meweb-screenshots-");
|
||||
AppServices.Folder = data.FullName;
|
||||
if (store) App.Platform = new StorePhone();
|
||||
|
||||
var session = HeadlessUnitTestSession.StartNew(typeof(ScreenshotEntry));
|
||||
await session.Dispatch(async () =>
|
||||
{
|
||||
if (store)
|
||||
{
|
||||
var invented = StoreRun.Finished(App.Services.GetRequiredService<KnowledgeBase>());
|
||||
var early = StoreRun.Early(invented);
|
||||
foreach (var (code, locale) in new[] { ("en", "en-US"), ("it", "it-IT") })
|
||||
{
|
||||
Localizer.Instance.SetLanguage(Languages.Find(code));
|
||||
var folder = Path.Combine(locale, "images", "phoneScreenshots");
|
||||
Phone(Path.Combine(folder, "2"), model => model.Replay(invented),
|
||||
view => view.GetVisualDescendants().OfType<TextBlock>().First(t => t.Text == Localizer.Instance["UsesTitle"]));
|
||||
Phone(Path.Combine(folder, "3"), model => model.Replay(invented));
|
||||
Phone(Path.Combine(folder, "1"), model => model.Status = Reachability.Online);
|
||||
Phone(Path.Combine(folder, "4"), model =>
|
||||
{
|
||||
model.Replay(invented);
|
||||
model.Cards.First(c => c.Id == CheckId.Nat).IsExpanded = true;
|
||||
}, view => view.GetVisualDescendants().OfType<Border>().First(b => b.Classes.Contains("card") && b.DataContext is CardViewModel { Id: CheckId.Nat }));
|
||||
Phone(Path.Combine(folder, "5"), model =>
|
||||
{
|
||||
model.Replay(early);
|
||||
model.Status = Reachability.Online;
|
||||
model.IsChecking = true;
|
||||
model.AskReach = false;
|
||||
model.OfferShare = false;
|
||||
model.Uses.Clear();
|
||||
foreach (var id in Enum.GetValues<UseId>()) model.Uses.Add(new UseViewModel(id, null));
|
||||
});
|
||||
Phone(Path.Combine(folder, "6"), model =>
|
||||
{
|
||||
model.Replay(invented);
|
||||
model.OpenShareCommand.Execute(null);
|
||||
}, view => view.GetVisualDescendants().OfType<TextBlock>().First(t => t.Text == Localizer.Instance["ShareExact"]));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
var run = await App.Services.GetRequiredService<CheckRunner>().Run((_, _) => { }, CancellationToken.None);
|
||||
Console.WriteLine($"run: {string.Join(", ", run.Findings.Select(f => $"{f.Id}={f.Outcome}"))}");
|
||||
foreach (var (width, height, label) in new[] { (1100, 1500, "desktop"), (400, 8000, "phone") })
|
||||
@@ -54,7 +95,15 @@ await session.Dispatch(async () =>
|
||||
data.Delete(true);
|
||||
Environment.Exit(0);
|
||||
|
||||
void Shoot(int width, int height, string name, Action<MainViewModel> prepare, Action<MainView> arrange = null)
|
||||
void Phone(string name, Action<MainViewModel> prepare, Func<MainView, Control> top = null) => Shoot(405, 720, name, prepare, top is null ? null : view =>
|
||||
{
|
||||
var target = top(view);
|
||||
var scroller = target.FindAncestorOfType<ScrollViewer>();
|
||||
var at = target.TranslatePoint(default, (Visual)scroller.Content);
|
||||
scroller.Offset = new Vector(0, Math.Max(0, (at?.Y ?? 0) - 8));
|
||||
}, 1080 / 405.0);
|
||||
|
||||
void Shoot(int width, int height, string name, Action<MainViewModel> prepare, Action<MainView> arrange = null, double scale = 1)
|
||||
{
|
||||
var fresh = AppSettings.Read();
|
||||
fresh.StorySeen = false;
|
||||
@@ -63,7 +112,19 @@ void Shoot(int width, int height, string name, Action<MainViewModel> prepare, Ac
|
||||
var view = new MainView { DataContext = model };
|
||||
var window = new Window { Width = width, Height = height, Content = view };
|
||||
window.Show();
|
||||
window.SetRenderScaling(scale);
|
||||
model.AvailableWidth = width;
|
||||
if (store)
|
||||
{
|
||||
var patience = Stopwatch.StartNew();
|
||||
do
|
||||
{
|
||||
Dispatcher.UIThread.RunJobs();
|
||||
Thread.Sleep(20);
|
||||
}
|
||||
while (model.Status == Reachability.Unknown && patience.Elapsed < TimeSpan.FromSeconds(20));
|
||||
model.LatestVersion = null;
|
||||
}
|
||||
prepare(model);
|
||||
for (var i = 0; i < 6; i++) Dispatcher.UIThread.RunJobs();
|
||||
if (arrange is not null)
|
||||
@@ -75,6 +136,7 @@ void Shoot(int width, int height, string name, Action<MainViewModel> prepare, Ac
|
||||
Dispatcher.UIThread.RunJobs();
|
||||
var frame = window.CaptureRenderedFrame();
|
||||
var path = Path.Combine(output, $"{name}.png");
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||
if (frame is not null)
|
||||
{
|
||||
using var file = File.Create(path);
|
||||
|
||||
Reference in new issue
Block a user