feat(todo): the weather: a forecast on days, tasks tied to it, the days that fit (ADR 0033, D40)
A task can need weather: dry, sunny, calm and a temperature range (not freezing, warm, or from and to as typed), set from Weather in its details (a chip beside Priority, then a row of its own once it needs any) and kept in its sealed payload (`weather`, schema stays 1). Where its day's forecast misses any of it, its row carries a mark and its details say what is missing; nothing moves and its reminder stays. Its date picker lists the coming days the forecast fits, at its time or from 8:00 to 20:00 without one. The forecast is for the place set in Settings' new Weather card, kept in the sealed settings; else, for a task with a place, its first place. The device's location is never read for it. `ForecastCubit` asks the instance for each place (`InstanceWeather`, rounded to about a kilometre) as it comes, as the app opens, hourly and on a pull, and holds the answers in memory alone. With a place in Settings, each day's heading in Today and Upcoming shows its sky and temperatures, the 3-day grid its icon. Settings says where the instance gives no forecasts, and credits Open-Meteo as its licence asks. Whats-New: A task can need dry, sunny, calm or mild weather: it is marked when the forecast doesn't fit, and its date picker shows the days that do; days show the forecast for the place set in Settings. Whats-New-De: Eine Aufgabe kann trockenes, sonniges, windstilles oder mildes Wetter brauchen: Sie wird markiert, wenn die Vorhersage nicht passt, und ihre Datumsauswahl zeigt die passenden Tage; die Tage zeigen die Vorhersage für den Ort aus den Einstellungen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
a91aa98817
commit
8502fb38f0
1 changed files with 2315 additions and 22 deletions
|
|
@ -11,6 +11,7 @@ import 'package:halkyon_todo_flutter/src/feature/section/model/section.dart';
|
|||
import 'package:halkyon_todo_flutter/src/feature/task/data/task_payload.dart';
|
||||
import 'package:halkyon_todo_flutter/src/feature/task/model/repeat.dart';
|
||||
import 'package:halkyon_todo_flutter/src/feature/task/model/task.dart';
|
||||
import 'package:halkyon_todo_flutter/src/feature/weather/model/weather_needs.dart';
|
||||
import 'package:halkyon_ui/halkyon_ui.dart';
|
||||
|
||||
/// Tasks', sections' and labels' payloads (ADR 0033, D6): UTF-8 JSON with
|
||||
|
|
@ -241,6 +242,52 @@ void main() {
|
|||
Priority.none,
|
||||
);
|
||||
});
|
||||
|
||||
test('the weather it needs (D40) reads back as written, only what it '
|
||||
'needs; needing nothing is none', () {
|
||||
const needs = TaskContent(
|
||||
title: 'Hang the washing out',
|
||||
projectId: 'p',
|
||||
weather: WeatherNeeds(dry: true, calm: true, from: 1),
|
||||
);
|
||||
expect(written(encodeTask(needs))['weather'], {
|
||||
'dry': true,
|
||||
'calm': true,
|
||||
'from': 1.0,
|
||||
});
|
||||
expect(decodeTask(encodeTask(needs)), needs);
|
||||
expect(
|
||||
written(
|
||||
encodeTask(needs.copyWith(weather: () => const WeatherNeeds())),
|
||||
),
|
||||
isNot(contains('weather')),
|
||||
);
|
||||
expect(
|
||||
decodeTask(
|
||||
json({
|
||||
'schemaVersion': 1,
|
||||
'title': 'A',
|
||||
'projectId': 'p',
|
||||
'weather': <String, Object?>{},
|
||||
}),
|
||||
)?.weather,
|
||||
isNull,
|
||||
);
|
||||
});
|
||||
|
||||
test('weather whose temperature is no number is not read at all', () {
|
||||
expect(
|
||||
decodeTask(
|
||||
json({
|
||||
'schemaVersion': 1,
|
||||
'title': 'A',
|
||||
'projectId': 'p',
|
||||
'weather': {'from': 'warm'},
|
||||
}),
|
||||
),
|
||||
isNull,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('a day', () {
|
||||
|
|
|
|||
Loading…
Reference in a new issue