refactor(branding): rename app Tanemaki → Tane

Public name is now Tane (種, "seed"); Tanemaki (種まき, "to scatter seeds")
is kept only as etymology in the About screen and onboarding.

App not yet distributed, so format tokens rename cleanly with no migration:
backup extension .tanemaki→.tane, QR scheme tanemaki://→tane://, file
prefixes tane-*. Website link and species-catalog User-Agent →
tane.comunes.org. Android label capitalised to "Tane".

Identity/crypto constants already use org.comunes.tane (derivation, HKDF
backup, sync namespace, TANE1 recovery tag) — left untouched, so keys,
backups and sync are unaffected. Tests updated; analyze + full suite green.
This commit is contained in:
vjrj 2026-07-12 13:04:16 +02:00
parent 2c113cc17d
commit a534c14983
34 changed files with 180 additions and 180 deletions

View file

@ -17,7 +17,7 @@ void main() {
setUp(() {
PackageInfo.setMockInitialValues(
appName: 'Tanemaki',
appName: 'Tane',
packageName: 'org.comunes.tane',
version: '0.1.0',
buildNumber: '1',
@ -38,7 +38,7 @@ void main() {
await tester.tap(find.text('About')); // drawer entry
await tester.pumpAndSettle();
expect(find.text('まき'), findsOneWidget);
expect(find.text(''), findsOneWidget);
expect(find.textContaining('digital Plantare'), findsOneWidget);
await disposeTree(tester);
});
@ -57,12 +57,12 @@ void main() {
await tester.pumpAndSettle();
// The backup section pushed the About tile below the fold.
await tester.scrollUntilVisible(find.text('About Tanemaki'), 200);
await tester.tap(find.text('About Tanemaki'));
await tester.scrollUntilVisible(find.text('About Tane'), 200);
await tester.tap(find.text('About Tane'));
await tester.pumpAndSettle();
// Explanation text and kanji are shown above the fold.
expect(find.text('まき'), findsOneWidget);
expect(find.text(''), findsOneWidget);
expect(find.textContaining('helps people and collectives'), findsOneWidget);
expect(find.textContaining('digital Plantare'), findsOneWidget);
@ -87,8 +87,8 @@ void main() {
await tester.pumpAndSettle();
await tester.tap(find.text('Settings'));
await tester.pumpAndSettle();
await tester.scrollUntilVisible(find.text('About Tanemaki'), 200);
await tester.tap(find.text('About Tanemaki'));
await tester.scrollUntilVisible(find.text('About Tane'), 200);
await tester.tap(find.text('About Tane'));
await tester.pumpAndSettle();
await tester.scrollUntilVisible(find.text('Open-source licenses'), 200);

View file

@ -109,12 +109,12 @@ void main() {
expect(find.text('Copy saved'), findsOneWidget);
});
testWidgets('saving a backup writes a sealed .tanemaki file', (tester) async {
testWidgets('saving a backup writes a sealed .tane file', (tester) async {
await tester.pumpWidget(section());
await tester.tap(find.text('Save a backup'));
await tester.pumpAndSettle();
expect(files.savedName, endsWith('.tanemaki'));
expect(files.savedName, endsWith('.tane'));
expect(BackupBox.looksSealed(files.savedBytes!), isTrue);
expect(find.text('Copy saved'), findsOneWidget);
});
@ -210,7 +210,7 @@ void main() {
await tester.pumpAndSettle();
expect(
find.text('This file could not be read as a Tanemaki copy'),
find.text('This file could not be read as a Tane copy'),
findsOneWidget,
);
});
@ -228,7 +228,7 @@ void main() {
await tester.tap(find.byKey(const Key('backup.recoverySave')));
await tester.pumpAndSettle();
expect(files.savedName, 'tanemaki-recovery.pdf');
expect(files.savedName, 'tane-recovery.pdf');
expect(String.fromCharCodes(files.savedBytes!.take(5)), '%PDF-');
// The seed itself never appears in the clear in the PDF stream metadata;
// the QR encodes the human code, which IS the secret that's the point

View file

@ -43,7 +43,7 @@ void main() {
const longLocales = [AppLocale.es, AppLocale.pt, AppLocale.ast];
setUpAll(() => PackageInfo.setMockInitialValues(
appName: 'Tanemaki',
appName: 'Tane',
packageName: 'org.comunes.tane',
version: '0.1.0',
buildNumber: '1',