feat(ui): Material 3 redesign, cover-photo viewer, About screen

Apply a Material 3 seed-green palette and rounded components across the
home, inventory, quick-add, quantity picker and variety-detail screens.
The full-screen photo viewer can now set any photo as the cover (via
attachment sort order) and delete after confirmation. Lot forms and
packaging surface as choice chips.

Extract About out of Settings into its own screen (app version via
package_info_plus, website link). Add es/en strings for the new lot
types, presentation, home tagline and About. Update Seedees v2 mockups.
This commit is contained in:
vjrj 2026-07-09 11:51:59 +02:00
parent f5c36f2369
commit 42c16c0e3f
24 changed files with 1960 additions and 416 deletions

View file

@ -45,6 +45,7 @@ class TranslationsEs extends Translations with BaseTranslations<AppLocale, Trans
@override late final _Translations$photo$es photo = _Translations$photo$es._(_root);
@override late final _Translations$menu$es menu = _Translations$menu$es._(_root);
@override late final _Translations$settings$es settings = _Translations$settings$es._(_root);
@override late final _Translations$about$es about = _Translations$about$es._(_root);
@override late final _Translations$inventory$es inventory = _Translations$inventory$es._(_root);
@override late final _Translations$quickAdd$es quickAdd = _Translations$quickAdd$es._(_root);
@override late final _Translations$detail$es detail = _Translations$detail$es._(_root);
@ -53,6 +54,7 @@ class TranslationsEs extends Translations with BaseTranslations<AppLocale, Trans
@override late final _Translations$addLot$es addLot = _Translations$addLot$es._(_root);
@override late final _Translations$harvest$es harvest = _Translations$harvest$es._(_root);
@override late final _Translations$lotType$es lotType = _Translations$lotType$es._(_root);
@override late final _Translations$presentation$es presentation = _Translations$presentation$es._(_root);
@override late final _Translations$unit$es unit = _Translations$unit$es._(_root);
}
@ -88,8 +90,11 @@ class _Translations$home$es extends Translations$home$en {
final TranslationsEs _root; // ignore: unused_field
// Translations
@override String get tagline => 'Comparte y cultiva semillas locales';
@override String get openMarket => 'Mercado abierto';
@override String get openMarketSubtitle => 'Explora e intercambia';
@override String get yourInventory => 'Tu inventario';
@override String get yourInventorySubtitle => 'Gestiona tus semillas';
}
// Path: photo
@ -101,6 +106,9 @@ class _Translations$photo$es extends Translations$photo$en {
// Translations
@override String get camera => 'Hacer una foto';
@override String get gallery => 'Elegir de la galería';
@override String get setAsCover => 'Poner de portada';
@override String get isCover => 'Foto de portada';
@override String get deleteConfirm => '¿Borrar esta foto?';
}
// Path: menu
@ -110,6 +118,7 @@ class _Translations$menu$es extends Translations$menu$en {
final TranslationsEs _root; // ignore: unused_field
// Translations
@override String get tagline => 'tu banco de semillas';
@override String get inventory => 'Inventario';
@override String get market => 'Mercado';
@override String get profile => 'Tu perfil';
@ -132,6 +141,27 @@ class _Translations$settings$es extends Translations$settings$en {
@override String get langEn => 'English';
@override String get about => 'Acerca de';
@override String get aboutText => 'Inventario local y cifrado para semillas tradicionales. AGPL-3.0.';
@override String get aboutOpen => 'Acerca de Tanemaki';
}
// Path: about
class _Translations$about$es extends Translations$about$en {
_Translations$about$es._(TranslationsEs root) : this._root = root, super.internal(root);
final TranslationsEs _root; // ignore: unused_field
// Translations
@override String get title => 'Acerca de';
@override String get kanji => '種まき';
@override String get tagline => 'Una app local-first y descentralizada para gestionar y compartir semillas y plantones tradicionales.';
@override String get intro => 'Tanemaki (種まき, «sembrar / esparcir semillas» en japonés; nombre corto Tane, 種 «semilla») ayuda a personas y colectivos a llevar un inventario amable de su banco de semillas, decidir qué ofrecen y compartirlo localmente — sin un intermediario central que pueda controlarlo, censurarlo o ser multado por ello. El objetivo es a la vez práctico y político: apoyar las variedades tradicionales de semillas y plantar cara al monopolio semillero.';
@override String get heritage => 'El nombre honra las viejas tradiciones japonesas de ayuda mutua en torno al arroz — yui (trabajo comunitario compartido) y tanomoshi (fondos de reciprocidad) — que inspiraron el papel Plantare, la «moneda comunitaria para el intercambio de semillas» (BAH-Semillero, 2009, CC-BY-SA). Tanemaki es el Plantare digital.';
@override String get version => 'Versión';
@override String get license => 'Licencia';
@override String get licenseValue => 'AGPL-3.0';
@override String get website => 'Sitio web';
@override String get openSourceLicenses => 'Licencias de código abierto';
@override String get openSourceLicensesSubtitle => 'Bibliotecas de terceros y sus licencias';
}
// Path: inventory
@ -265,7 +295,27 @@ class _Translations$lotType$es extends Translations$lotType$en {
// Translations
@override String get seed => 'Semillas';
@override String get plant => 'Plantel';
@override String get plant => 'Planta';
@override String get seedling => 'Plantón';
@override String get tree => 'Árbol / arbusto';
@override String get bulb => 'Bulbo / tubérculo';
@override String get cutting => 'Esqueje';
}
// Path: presentation
class _Translations$presentation$es extends Translations$presentation$en {
_Translations$presentation$es._(TranslationsEs root) : this._root = root, super.internal(root);
final TranslationsEs _root; // ignore: unused_field
// Translations
@override String get title => 'Envase';
@override String get none => 'Sin especificar';
@override String get pot => 'Maceta';
@override String get tray => 'Bandeja';
@override String get plug => 'Alvéolo';
@override String get bareRoot => 'Raíz desnuda';
@override String get rootBall => 'Cepellón';
}
// Path: unit
@ -298,6 +348,9 @@ class _Translations$unit$es extends Translations$unit$en {
@override late final _Translations$unit$plant$es plant = _Translations$unit$plant$es._(_root);
@override late final _Translations$unit$pot$es pot = _Translations$unit$pot$es._(_root);
@override late final _Translations$unit$tray$es tray = _Translations$unit$tray$es._(_root);
@override late final _Translations$unit$seedling$es seedling = _Translations$unit$seedling$es._(_root);
@override late final _Translations$unit$tree$es tree = _Translations$unit$tree$es._(_root);
@override late final _Translations$unit$cutting$es cutting = _Translations$unit$cutting$es._(_root);
@override late final _Translations$unit$grams$es grams = _Translations$unit$grams$es._(_root);
@override late final _Translations$unit$count$es count = _Translations$unit$count$es._(_root);
}
@ -511,6 +564,39 @@ class _Translations$unit$tray$es extends Translations$unit$tray$en {
@override String get plural => 'bandejas';
}
// Path: unit.seedling
class _Translations$unit$seedling$es extends Translations$unit$seedling$en {
_Translations$unit$seedling$es._(TranslationsEs root) : this._root = root, super.internal(root);
final TranslationsEs _root; // ignore: unused_field
// Translations
@override String get singular => 'plántula';
@override String get plural => 'plántulas';
}
// Path: unit.tree
class _Translations$unit$tree$es extends Translations$unit$tree$en {
_Translations$unit$tree$es._(TranslationsEs root) : this._root = root, super.internal(root);
final TranslationsEs _root; // ignore: unused_field
// Translations
@override String get singular => 'árbol';
@override String get plural => 'árboles';
}
// Path: unit.cutting
class _Translations$unit$cutting$es extends Translations$unit$cutting$en {
_Translations$unit$cutting$es._(TranslationsEs root) : this._root = root, super.internal(root);
final TranslationsEs _root; // ignore: unused_field
// Translations
@override String get singular => 'esqueje';
@override String get plural => 'esquejes';
}
// Path: unit.grams
class _Translations$unit$grams$es extends Translations$unit$grams$en {
_Translations$unit$grams$es._(TranslationsEs root) : this._root = root, super.internal(root);
@ -548,10 +634,17 @@ extension on TranslationsEs {
'common.edit' => 'Editar',
'common.type' => 'Tipo',
'common.comingSoon' => 'Pronto',
'home.tagline' => 'Comparte y cultiva semillas locales',
'home.openMarket' => 'Mercado abierto',
'home.openMarketSubtitle' => 'Explora e intercambia',
'home.yourInventory' => 'Tu inventario',
'home.yourInventorySubtitle' => 'Gestiona tus semillas',
'photo.camera' => 'Hacer una foto',
'photo.gallery' => 'Elegir de la galería',
'photo.setAsCover' => 'Poner de portada',
'photo.isCover' => 'Foto de portada',
'photo.deleteConfirm' => '¿Borrar esta foto?',
'menu.tagline' => 'tu banco de semillas',
'menu.inventory' => 'Inventario',
'menu.market' => 'Mercado',
'menu.profile' => 'Tu perfil',
@ -565,6 +658,18 @@ extension on TranslationsEs {
'settings.langEn' => 'English',
'settings.about' => 'Acerca de',
'settings.aboutText' => 'Inventario local y cifrado para semillas tradicionales. AGPL-3.0.',
'settings.aboutOpen' => 'Acerca de Tanemaki',
'about.title' => 'Acerca de',
'about.kanji' => '種まき',
'about.tagline' => 'Una app local-first y descentralizada para gestionar y compartir semillas y plantones tradicionales.',
'about.intro' => 'Tanemaki (種まき, «sembrar / esparcir semillas» en japonés; nombre corto Tane, 種 «semilla») ayuda a personas y colectivos a llevar un inventario amable de su banco de semillas, decidir qué ofrecen y compartirlo localmente — sin un intermediario central que pueda controlarlo, censurarlo o ser multado por ello. El objetivo es a la vez práctico y político: apoyar las variedades tradicionales de semillas y plantar cara al monopolio semillero.',
'about.heritage' => 'El nombre honra las viejas tradiciones japonesas de ayuda mutua en torno al arroz — yui (trabajo comunitario compartido) y tanomoshi (fondos de reciprocidad) — que inspiraron el papel Plantare, la «moneda comunitaria para el intercambio de semillas» (BAH-Semillero, 2009, CC-BY-SA). Tanemaki es el Plantare digital.',
'about.version' => 'Versión',
'about.license' => 'Licencia',
'about.licenseValue' => 'AGPL-3.0',
'about.website' => 'Sitio web',
'about.openSourceLicenses' => 'Licencias de código abierto',
'about.openSourceLicensesSubtitle' => 'Bibliotecas de terceros y sus licencias',
'inventory.title' => 'Inventario',
'inventory.searchHint' => 'Buscar semillas',
'inventory.empty' => 'Aún no hay semillas. Toca + para añadir la primera.',
@ -624,7 +729,18 @@ extension on TranslationsEs {
'harvest.monthNames.10' => 'noviembre',
'harvest.monthNames.11' => 'diciembre',
'lotType.seed' => 'Semillas',
'lotType.plant' => 'Plantel',
'lotType.plant' => 'Planta',
'lotType.seedling' => 'Plantón',
'lotType.tree' => 'Árbol / arbusto',
'lotType.bulb' => 'Bulbo / tubérculo',
'lotType.cutting' => 'Esqueje',
'presentation.title' => 'Envase',
'presentation.none' => 'Sin especificar',
'presentation.pot' => 'Maceta',
'presentation.tray' => 'Bandeja',
'presentation.plug' => 'Alvéolo',
'presentation.bareRoot' => 'Raíz desnuda',
'presentation.rootBall' => 'Cepellón',
'unit.aFew' => 'unas pocas',
'unit.some' => 'algunas',
'unit.plenty' => 'muchas',
@ -667,6 +783,12 @@ extension on TranslationsEs {
'unit.pot.plural' => 'macetas',
'unit.tray.singular' => 'bandeja',
'unit.tray.plural' => 'bandejas',
'unit.seedling.singular' => 'plántula',
'unit.seedling.plural' => 'plántulas',
'unit.tree.singular' => 'árbol',
'unit.tree.plural' => 'árboles',
'unit.cutting.singular' => 'esqueje',
'unit.cutting.plural' => 'esquejes',
'unit.grams.singular' => 'gramo',
'unit.grams.plural' => 'gramos',
'unit.count.singular' => 'semilla',