Files
harbour-henflow/README.md
T

7.4 KiB

harbour-henflow

Porting nativo Sailfish OS dell'app Android Henflow (it.carlobaratto.henflow). UI in QML/Silica, calcolo e dati locali, pubblicazione prevista sullo store Jolla Harbour.

Il porting non usa il runtime Flutter community (flutter-sailfishos): quello resta una via OpenRepos, non Harbour-safe, e non supporta i plugin nativi Android (AdMob/File picker/Share). Nessun account, nessun cloud, come l'originale.

Sorgenti di riferimento

  • Flutter (originale): workspace/henflow-flutter — export da Nextcloud, repo Gitea HenFlow.
  • Screenshot dello store usati come riferimento UI.

Stato

parte stato
Packaging (spec RPM, desktop SailJail, icone, i18n) pronto
Livello dati C++ (src/datastore.*, JSON compatibile con l'app Android) fatto e verificato
Motore di calcolo (qml/js/henflow.js) portato e verificato con node
Traduzioni 4 lingue (qml/js/i18n.js, 126 chiavi) portate e verificate con node
Catalogo razze con foto (qml/js/catalog.js) portato e verificato con node
Home con produzione stimata e coda ordini fatta
Scheda ordine (nuovo/modifica, data calcolata) fatta
Cover con produzione e ordini pendenti fatta
Razze / pollaio / galline, clienti, backup, lingua, intro da fare

Struttura

harbour-henflow.pro          # QT += quick qml, INSTALLS icone
rpm/harbour-henflow.spec     # lrelease + desktop cercati con find (layout sorgente variabile)
rpm/harbour-henflow.desktop  # profilo [X-Sailjail] esplicito (dati persistenti)
src/main.cpp                 # SailfishApp, context property appSettings/appData, lingua
src/settings.h/.cpp          # QSettings su path esplicito AppConfigLocation + sync()
src/datastore.h/.cpp         # dati in un JSON in AppConfigLocation (chiavi = SharedPreferences dell'app)
qml/harbour-henflow.qml      # ApplicationWindow: initialPage + cover
qml/pages/MainPage.qml       # Home: produzione stimata, coda ordini, menu nuovo ordine
qml/pages/OrderPage.qml      # nuovo/modifica ordine con anteprima della data di consegna
qml/cover/CoverPage.qml      # produzione del giorno e ordini pendenti
qml/js/henflow.js            # motore di calcolo (ES5, testabile con node)
qml/js/i18n.js               # 126 chiavi x 4 lingue + t(chiave, arg, lingua)
qml/js/catalog.js            # 7 razze: nome/descrizione/colore uova/foto
assets/breeds/*.jpg          # foto delle razze (installate nel datadir)
tools/gen_from_flutter.py    # rigenera i18n.js e catalog.js dai sorgenti Flutter
tests/run.sh                 # motore + traduzioni (node)
tests/cpp_test.sh            # livello dati (Qt 5.15 locale, config in cartella temporanea)
icons/make_icons.py          # icone 86/108/128/172 dall'artwork originale
translations/*.ts            # stringhe statiche QML (il testo dell'app viene da i18n.js)

Test

sh tests/run.sh        # motore di calcolo + traduzioni e catalogo (node, nessuna dipendenza)
sh tests/cpp_test.sh   # livello dati: compila src/datastore.cpp col Qt locale e prova
                       # persistenza, rilettura, compatibilita' delle chiavi, backup, file corrotto

Il testo dell'app vive in i18n.js (come il TranslationService dell'originale), quindi la lingua cambia a runtime senza riavviare l'app: cosa che i .ts di Qt 5.6 non permettono. La lingua predefinita segue quella del telefono.

Motore di calcolo (portato fedelmente da lib/main.dart)

  • Produzione stimata per razza = galline in deposizione x uova/gallina/giorno (catalogo: tutte 1.0). Una gallina conta da 6 mesi in su (_ageInMonths).
  • Magazzino: all'apertura, i giorni passati dall'ultimo aggiornamento aggiungono la produzione giornaliera alle scorte di ogni razza attiva.
  • Coda FIFO: ordini in ordine di creazione; ognuno consuma le scorte virtuali della sua razza, chi le trova consegna oggi, gli altri aspettano ceil(uova_mancanti / produzione) giorni. Gli ordini gia' consegnati non consumano scorte.
  • Stima per un nuovo ordine: ceil((pendenti + richieste - scorte) / produzione).

Le date sono sempre normalizzate a YYYY-MM-DD e le funzioni non mutano l'input.

Modello dati (fedele a StorageService, SharedPreferences + JSON)

chiave contenuto
breed_settings_v2 [{breedId, hens:[{id, name, birthDate, isLaying}]}]
reservations_v2 [{id, customerName, breedId, eggsRequested, createdAt, deliveryDate, isDelivered}]
customers_v1 [{id, firstName, lastName, phoneNumber}]
warehouse_stock_v1 {breedId: uova}
last_production_update_v1 data ISO dell'ultimo accrual

Nel porting: un unico file JSON in ~/.config/harbour/henflow/ (nessuna dipendenza extra, nessun driver SQL da verificare sul device) con la stessa struttura, cosi' il backup/ripristino resta compatibile con l'app Android.

Schermate mappate (da sorgenti + screenshot)

schermata Flutter contenuto porting
OnboardingPage 4 passi introduttivi da fare
ModeSelectionPage modalita' allevatore / cliente da decidere
HomePage tab Orders list / Calendar (+ magazzino), card produzione stimata, card ordini con stato e azioni (condividi/modifica/elimina), FAB New order da fare
SettingsPage tab Available breeds (catalogo con foto e spunta) / My coop (galline registrate, in deposizione, produzione) + backup/ripristino JSON + lingua da fare
BreedDetailPage galline della razza, eta' in mesi, stato deposizione da fare
CustomersPage + dialoghi anagrafica clienti, nuovo ordine da fare
AboutPage info app da fare
CoopIcon (CustomPainter) icona pollaio disegnata a mano da ridisegnare (Canvas QML o PNG)

Differenze da tenere presenti: niente annunci (AdMob non esiste su Sailfish), share/export via file JSON in Download invece di share_plus/file_picker.

Build e deploy

Sul PC con l'SDK Sailfish (qui non c'e' sfdk):

sfdk target use SailfishOS-5.0.0.62-aarch64   # o il target del tuo device
sfdk build                                    # RPM in build-*/RPMS/
sfdk deploy                                   # oppure Qt Creator

Tarball per lo store (con --prefix, esclude .git e i file non tracciati):

git archive --format=tar.gz --prefix=harbour-henflow-0.1.0/ -o harbour-henflow-0.1.0.tar.gz HEAD

Aperti

  1. Schermate da fare: razze disponibili / mio pollaio / anagrafica galline, clienti, backup-ripristino, scelta lingua, introduzione iniziale, calendario.
  2. Verifica su device: la UI Silica non e' verificabile senza SDK/dispositivo (qui si verificano solo motore, traduzioni, catalogo e livello dati).

Correzioni rispetto all'originale (bug trovati nei sorgenti Flutter)

  • app_language.dart e' una copia vecchia della tabella traduzioni (111 chiavi contro 126), usata solo da lib/dialogs/confirm_dialogs.dart, e ha gli a capo scritti \\n: quei dialoghi mostrano un backslash visibile. Il porting estrae dalla tabella viva in main.dart.
  • Il francese ha 2 chiavi in meno (name_generic, desc_generic) e t() non ha fallback: in francese la razza "generic" usciva come testo name_generic. Nel porting i buchi sono colmati dall'inglese e un test lo verifica.
  • assets/breeds/olive.jpg era un WEBP con estensione .jpg: Qt 5.6 su Sailfish non ha il plugin webp. Riconvertito in JPEG.
  • Niente annunci (AdMob non esiste su Sailfish) e niente share_plus/file_picker: export/import JSON in Download.