feat: color a site from its address, and offer a failed web page to the system browser
This commit is contained in:
parent
56db479df0
commit
9d9f09ebc7
24 changed files with 597 additions and 25 deletions
85
app/test/site_palette_test.dart
Normal file
85
app/test/site_palette_test.dart
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mews/mews/document.dart';
|
||||
import 'package:mews/presentation/reader/oklch.dart';
|
||||
import 'package:mews/presentation/reader/palettes.dart';
|
||||
import 'package:mews/presentation/reader/site_palette.dart';
|
||||
|
||||
/// A wide sample of what the generator can produce: enough hosts to cover all
|
||||
/// 24 hues, 3 background tints and both foregrounds.
|
||||
Iterable<MewsPalette> _allPalettes(bool dark) => [
|
||||
for (var i = 0; i < 2000; i++) sitePalette('gemini://h$i.example/', dark: dark)!,
|
||||
];
|
||||
|
||||
void main() {
|
||||
group('seed', () {
|
||||
test('comes from the host', () {
|
||||
expect(siteSeed('gemini://example.org/page'), 'example.org');
|
||||
expect(siteSeed('gemini://Example.ORG/page'), 'example.org');
|
||||
});
|
||||
|
||||
test('names the user on a personal page', () {
|
||||
expect(siteSeed('gemini://example.org/~alice/'), 'alice@example.org');
|
||||
expect(siteSeed('gemini://example.org/users/alice/x.gmi'), 'alice@example.org');
|
||||
expect(siteSeed('gemini://example.org/Users/Alice'), 'alice@example.org');
|
||||
});
|
||||
|
||||
test('is empty without a host', () {
|
||||
expect(siteSeed('mews:settings'), '');
|
||||
expect(siteSeed('not a url'), '');
|
||||
});
|
||||
});
|
||||
|
||||
group('palette', () {
|
||||
test('is the same every time for one address', () {
|
||||
expect(sitePalette('gemini://example.org/a', dark: false),
|
||||
same(sitePalette('gemini://example.org/b', dark: false)));
|
||||
});
|
||||
|
||||
test('differs between two users on one host', () {
|
||||
final alice = sitePalette('gemini://example.org/~alice/', dark: false)!;
|
||||
final bob = sitePalette('gemini://example.org/~bob/', dark: false)!;
|
||||
expect(alice.link, isNot(bob.link));
|
||||
});
|
||||
|
||||
test('is null for an address with no host', () {
|
||||
expect(sitePalette('mews:settings', dark: false), isNull);
|
||||
});
|
||||
|
||||
test('falls back to plain when the reader asks for host colors', () {
|
||||
expect(
|
||||
paletteFor(
|
||||
pageVariant: MewsVariant.plain,
|
||||
readerVariant: 'host',
|
||||
dark: false,
|
||||
url: 'mews:settings'),
|
||||
paletteFor(pageVariant: MewsVariant.plain, readerVariant: 'plain', dark: false),
|
||||
);
|
||||
});
|
||||
|
||||
// Spec 5.1: every text and link color meets 7:1 against its background.
|
||||
for (final dark in [false, true]) {
|
||||
test('meets 7:1 contrast in ${dark ? 'dark' : 'light'} mode', () {
|
||||
for (final palette in _allPalettes(dark)) {
|
||||
expect(contrastRatio(palette.background, palette.foreground),
|
||||
greaterThanOrEqualTo(7.0));
|
||||
expect(contrastRatio(palette.background, palette.link),
|
||||
greaterThanOrEqualTo(7.0));
|
||||
expect(contrastRatio(palette.background, palette.visited),
|
||||
greaterThanOrEqualTo(7.0));
|
||||
}
|
||||
});
|
||||
|
||||
test('stays no louder than the fixed palettes in ${dark ? 'dark' : 'light'} mode', () {
|
||||
// Cool holds the most saturated link of the fixed palettes, so no
|
||||
// generated color may pass it.
|
||||
final cool = paletteFor(
|
||||
pageVariant: MewsVariant.cool, readerVariant: 'cool', dark: dark);
|
||||
final limit = chromaOf(cool.link);
|
||||
for (final palette in _allPalettes(dark)) {
|
||||
expect(chromaOf(palette.link), lessThanOrEqualTo(limit));
|
||||
expect(chromaOf(palette.background), lessThanOrEqualTo(0.03));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue