Screens / lists
Tasks
Groups tasks into overdue, today, upcoming, undated and done, each with its checkbox, with a quick add line and a sheet to edit the due day and priority.
Import
Tasks is part of Fliin Pro. With a license key, sign in once with fliin login, then add it in a Flutter app where fliin init has run:
fliin login
fliin add tasksAlso installs: alert, app-bar, button, core, date-field, empty-state, field, link-button, page, section-header, segmented, separator, sheet, skeleton, surface, task-row, text, text-field, time-field
Examples
List
The task list loaded from the service: what is overdue, today and later, each task ticked off in place. standalone holds its own controller over the service you pass; the sample day keeps the example stable.
import 'package:your_app/ui/fliin/screens/tasks/tasks_controller.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_data.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_screen.dart';
import 'package:flutter/widgets.dart';
class TasksListExample extends StatelessWidget {
const TasksListExample({super.key});
static final _today = DateTime(2026, 10, 27);
@override
Widget build(BuildContext context) {
return TasksScreen.standalone(
service: SampleTasksService(today: _today, latency: const Duration(milliseconds: 600)),
initial: TasksShown(sampleTasks(_today)),
now: () => DateTime(2026, 10, 27, 10),
onBack: () {},
);
}
}Adding
Two tasks being added: one is on its way, the server refused the other, and a notice says so with a way to try again. standalone holds its own controller over the service you pass; the sample day keeps the example stable.
import 'package:your_app/ui/fliin/screens/tasks/tasks_controller.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_data.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_screen.dart';
import 'package:flutter/widgets.dart';
class TasksAddingExample extends StatelessWidget {
const TasksAddingExample({super.key});
static final _today = DateTime(2026, 10, 27);
@override
Widget build(BuildContext context) {
return TasksScreen.standalone(
service: SampleTasksService(today: _today, latency: const Duration(milliseconds: 600)),
initial: TasksShown(
sampleTasks(_today),
adding: const [
TaskAdd(TaskDraft(key: 'k1', title: 'Buy bread')),
TaskAdd(TaskDraft(key: 'k2', title: 'Call the bank'), failed: true),
],
notice: const TasksNotice(TasksNoticeKind.addFailed, 'Call the bank'),
),
now: () => DateTime(2026, 10, 27, 10),
onBack: () {},
);
}
}Deleted
A task just deleted: it stays crossed out with an undo until the deletion goes to the service. standalone holds its own controller over the service you pass; the sample day keeps the example stable.
import 'package:your_app/ui/fliin/screens/tasks/tasks_controller.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_data.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_screen.dart';
import 'package:flutter/widgets.dart';
class TasksDeletedExample extends StatelessWidget {
const TasksDeletedExample({super.key});
static final _today = DateTime(2026, 10, 27);
@override
Widget build(BuildContext context) {
return TasksScreen.standalone(
service: SampleTasksService(today: _today, latency: Duration.zero),
initial: TasksShown(sampleTasks(_today), removed: const {'t3': TaskRemoval(undoable: true)}),
now: () => DateTime(2026, 10, 27, 10),
onBack: () {},
);
}
}Save failed
A tick the server could not save: the task goes back and a notice says which one. standalone holds its own controller over the service you pass; the sample day keeps the example stable.
import 'package:your_app/ui/fliin/screens/tasks/tasks_controller.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_data.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_screen.dart';
import 'package:flutter/widgets.dart';
class TasksSaveFailedExample extends StatelessWidget {
const TasksSaveFailedExample({super.key});
static final _today = DateTime(2026, 10, 27);
@override
Widget build(BuildContext context) {
return TasksScreen.standalone(
service: SampleTasksService(today: _today, latency: const Duration(milliseconds: 600)),
initial: TasksShown(sampleTasks(_today), notice: const TasksNotice(TasksNoticeKind.doneFailed, 'Pay the rent')),
now: () => DateTime(2026, 10, 27, 10),
onBack: () {},
);
}
}Empty
No task yet: the screen invites to add the first one. standalone holds its own controller over the service you pass; the sample day keeps the example stable.
import 'package:your_app/ui/fliin/screens/tasks/tasks_controller.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_data.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_screen.dart';
import 'package:flutter/widgets.dart';
class TasksEmptyExample extends StatelessWidget {
const TasksEmptyExample({super.key});
static final _today = DateTime(2026, 10, 27);
@override
Widget build(BuildContext context) {
return TasksScreen.standalone(
service: SampleTasksService(today: _today, latency: const Duration(milliseconds: 600)),
initial: const TasksShown([]),
now: () => DateTime(2026, 10, 27, 10),
onBack: () {},
);
}
}Loading
While the service answers, placeholders keep the shape of the list. standalone holds its own controller over the service you pass; the sample day keeps the example stable.
import 'package:your_app/ui/fliin/screens/tasks/tasks_controller.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_data.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_screen.dart';
import 'package:flutter/widgets.dart';
class TasksLoadingExample extends StatelessWidget {
const TasksLoadingExample({super.key});
static final _today = DateTime(2026, 10, 27);
@override
Widget build(BuildContext context) {
return TasksScreen.standalone(
service: SampleTasksService(today: _today, latency: const Duration(milliseconds: 600)),
initial: const TasksLoading(),
now: () => DateTime(2026, 10, 27, 10),
onBack: () {},
);
}
}Error
When loading fails, the screen says so and offers to try again. standalone holds its own controller over the service you pass; the sample day keeps the example stable.
import 'package:your_app/ui/fliin/screens/tasks/tasks_controller.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_data.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_screen.dart';
import 'package:flutter/widgets.dart';
class TasksErrorExample extends StatelessWidget {
const TasksErrorExample({super.key});
static final _today = DateTime(2026, 10, 27);
@override
Widget build(BuildContext context) {
return TasksScreen.standalone(
service: SampleTasksService(today: _today, latency: const Duration(milliseconds: 600)),
initial: const TasksFailed(),
now: () => DateTime(2026, 10, 27, 10),
onBack: () {},
);
}
}Offline
Without a connection, the screen asks to reconnect rather than showing an error. standalone holds its own controller over the service you pass; the sample day keeps the example stable.
import 'package:your_app/ui/fliin/screens/tasks/tasks_controller.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_data.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_screen.dart';
import 'package:flutter/widgets.dart';
class TasksOfflineExample extends StatelessWidget {
const TasksOfflineExample({super.key});
static final _today = DateTime(2026, 10, 27);
@override
Widget build(BuildContext context) {
return TasksScreen.standalone(
service: SampleTasksService(today: _today, latency: const Duration(milliseconds: 600)),
initial: const TasksOffline(),
now: () => DateTime(2026, 10, 27, 10),
onBack: () {},
);
}
}Project
A project's list: title names it, header shows its progress above the sections, and showDone: false lets a checked task leave the screen.
import 'package:your_app/ui/fliin/components/progress/fl_progress.dart';
import 'package:your_app/ui/fliin/components/text/fl_text.dart';
import 'package:your_app/ui/fliin/core/fliin.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_controller.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_data.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_screen.dart';
import 'package:flutter/widgets.dart';
class TasksProjectExample extends StatelessWidget {
const TasksProjectExample({super.key});
static final _today = DateTime(2026, 10, 27);
@override
Widget build(BuildContext context) {
final tasks = sampleTasks(_today);
final done = tasks.where((task) => task.done).length;
final space = FlScope.of(context).space;
return TasksScreen.standalone(
service: SampleTasksService(today: _today, latency: const Duration(milliseconds: 600)),
initial: TasksShown(tasks),
now: () => DateTime(2026, 10, 27, 10),
title: 'Moving house',
showDone: false,
header: Padding(
padding: EdgeInsetsDirectional.fromSTEB(space.lg, space.sm, space.lg, space.sm),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
spacing: space.sm,
children: [
FlText('$done of ${tasks.length} done', type: FlTextType.bodySm, tone: FlTextTone.muted),
FlProgress.linear(value: done / tasks.length, label: 'Progress'),
],
),
),
onBack: () {},
);
}
}Routing
fliin add tasks prints the route for the router it finds in your pubspec, a file next to the page that wires its navigation. Each of them:
go_router
// lib/tasks_route.dart, next to tasks_page.dart.
import 'package:go_router/go_router.dart';
import 'tasks_page.dart';
/// Add tasksRoute to the routes of your GoRouter.
final tasksRoute = GoRoute(
path: '/tasks',
builder: (context, state) => TasksPage(
// Alone in the stack (deep link, go): your app's home.
onBack: () => context.canPop() ? context.pop() : context.go('/'),
),
);navigator
// lib/tasks_route.dart, next to tasks_page.dart.
import 'package:flutter/material.dart';
import 'tasks_page.dart';
/// Opens “Tasks”: `Navigator.of(context).push(tasksRoute())`.
Route<void> tasksRoute() => MaterialPageRoute<void>(
builder: (context) => TasksPage(
onBack: () => Navigator.of(context).maybePop(),
),
);State
The controller is a ChangeNotifier from widgets.dart, with no package. fliin add tasks prints the page that holds it with the state management it finds, its imports written for your package; below they read your_app. Your backend implements the Service interface of the screen's _data.dart file:
none
// lib/tasks_page.dart
// Your backend: implement TasksService (tasks_data.dart) and pass it instead of the sample service.
import 'package:your_app/ui/fliin/screens/tasks/tasks_data.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_screen.dart';
import 'package:flutter/widgets.dart';
/// A single sample service for the whole app: what you check, add or
/// delete stays from one opening of the screen to the next.
final sampleTasksService = SampleTasksService(today: DateTime.now());
class TasksPage extends StatelessWidget {
const TasksPage({
super.key,
required this.onBack,
});
final VoidCallback onBack;
@override
Widget build(BuildContext context) => TasksScreen.standalone(
service: sampleTasksService,
onBack: onBack,
);
}provider
// lib/tasks_page.dart
// Your backend: implement TasksService (tasks_data.dart) and pass it instead of the sample service.
import 'package:your_app/ui/fliin/screens/tasks/tasks_controller.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_data.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_screen.dart';
import 'package:flutter/widgets.dart';
import 'package:provider/provider.dart';
/// A single sample service for the whole app: what you check, add or
/// delete stays from one opening of the screen to the next.
final sampleTasksService = SampleTasksService(today: DateTime.now());
class TasksPage extends StatelessWidget {
const TasksPage({
super.key,
required this.onBack,
});
final VoidCallback onBack;
@override
Widget build(BuildContext context) => ChangeNotifierProvider(
create: (_) => TasksController(service: sampleTasksService)..load(),
child: Builder(
builder: (context) => TasksScreen(
controller: context.read<TasksController>(),
onBack: onBack,
),
),
);
}riverpod
// lib/tasks_page.dart
// Your backend: implement TasksService (tasks_data.dart) and pass it instead of the sample service.
import 'package:your_app/ui/fliin/screens/tasks/tasks_controller.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_data.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_screen.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
/// A single sample service for the whole app: what you check, add or
/// delete stays from one opening of the screen to the next.
final sampleTasksService = SampleTasksService(today: DateTime.now());
final tasksControllerProvider = Provider.autoDispose<TasksController>((ref) {
final controller = TasksController(service: sampleTasksService)..load();
ref.onDispose(controller.dispose);
return controller;
});
class TasksPage extends ConsumerWidget {
const TasksPage({
super.key,
required this.onBack,
});
final VoidCallback onBack;
@override
Widget build(BuildContext context, WidgetRef ref) => TasksScreen(
controller: ref.watch(tasksControllerProvider),
onBack: onBack,
);
}bloc
// lib/tasks_page.dart
// Your backend: implement TasksService (tasks_data.dart) and pass it instead of the sample service.
import 'package:your_app/ui/fliin/screens/tasks/tasks_controller.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_data.dart';
import 'package:your_app/ui/fliin/screens/tasks/tasks_screen.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
/// A single sample service for the whole app: what you check, add or
/// delete stays from one opening of the screen to the next.
final sampleTasksService = SampleTasksService(today: DateTime.now());
/// The screen's controller as a bloc, for your BlocListener and BlocBuilder:
/// one emission per controller notification. `version` tells them apart
/// when `state` does not change (mode, filters, text…, read them on
/// `controller`). The screen listens to the controller itself.
class TasksCubit extends Cubit<({TasksState state, int version})> {
TasksCubit(this.controller) : super((state: controller.state, version: 0)) {
controller.addListener(_changed);
}
final TasksController controller;
void _changed() => emit((state: controller.state, version: state.version + 1));
@override
Future<void> close() {
controller
..removeListener(_changed)
..dispose();
return super.close();
}
}
class TasksPage extends StatelessWidget {
const TasksPage({
super.key,
required this.onBack,
});
final VoidCallback onBack;
@override
Widget build(BuildContext context) => BlocProvider(
create: (_) => TasksCubit(TasksController(service: sampleTasksService)..load()),
child: Builder(
builder: (context) => TasksScreen(
controller: context.read<TasksCubit>().controller,
onBack: onBack,
),
),
);
}API
TasksScreen: class extends StatefulWidget
TasksScreen.new: const new({super.key, required TasksController controller, VoidCallback? onBack, DateTime Function() now, TasksDateFormat? formatDate, TasksTimeFormat? formatTime, String? title, bool showDone, Widget? header})
TasksScreen.standalone: const new({super.key, required TasksService service, TasksState? initial, VoidCallback? onBack, DateTime Function() now, TasksDateFormat? formatDate, TasksTimeFormat? formatTime, String? title, bool showDone, Widget? header})
TasksScreen.controller: get TasksController?
TasksScreen.service: get TasksService?
TasksScreen.initial: get TasksState?
TasksScreen.onBack: get VoidCallback?
TasksScreen.now: get DateTime Function()
TasksScreen.formatDate: get TasksDateFormat?
TasksScreen.formatTime: get TasksTimeFormat?
TasksScreen.title: get String?
TasksScreen.showDone: get bool
TasksScreen.header: get Widget?
TasksScreen.createState: State<TasksScreen>()
TasksState: sealed class permits {TasksFailed, TasksLoading, TasksOffline, TasksShown}
TasksState.new: const new()
TasksLoading: final class extends TasksState
TasksLoading.new: const new()
TasksFailed: final class extends TasksState
TasksFailed.new: const new()
TasksOffline: final class extends TasksState
TasksOffline.new: const new()
TaskRemoval: final class
TaskRemoval.new: const new({required bool undoable})
TaskRemoval.undoable: get bool
TaskAdd: final class
TaskAdd.new: const new(TaskDraft draft, {bool failed})
TaskAdd.draft: get TaskDraft
TaskAdd.failed: get bool
TasksNoticeKind: enum {doneFailed, addFailed, deleteFailed, refreshFailed, refreshOffline}
TasksNoticeKind.doneFailed: static final TasksNoticeKind
TasksNoticeKind.addFailed: static final TasksNoticeKind
TasksNoticeKind.deleteFailed: static final TasksNoticeKind
TasksNoticeKind.refreshFailed: static final TasksNoticeKind
TasksNoticeKind.refreshOffline: static final TasksNoticeKind
TasksNotice: final class
TasksNotice.new: const new(TasksNoticeKind kind, [String? title])
TasksNotice.kind: get TasksNoticeKind
TasksNotice.title: get String?
TasksShown: final class extends TasksState
TasksShown.new: const new(List<Task> tasks, {Map<String, TaskRemoval> removed, List<TaskAdd> adding, bool refreshing, TasksNotice? notice})
TasksShown.tasks: get List<Task>
TasksShown.removed: get Map<String, TaskRemoval>
TasksShown.adding: get List<TaskAdd>
TasksShown.refreshing: get bool
TasksShown.notice: get TasksNotice?
TasksShown.isEmpty: get bool
TaskSaveOutcome: enum {saved, offline, failed, missing}
TaskSaveOutcome.saved: static final TaskSaveOutcome
TaskSaveOutcome.offline: static final TaskSaveOutcome
TaskSaveOutcome.failed: static final TaskSaveOutcome
TaskSaveOutcome.missing: static final TaskSaveOutcome
TasksController: class extends ChangeNotifier
TasksController.new: new({required TasksService service, TasksState initial, Duration undoDelay, String Function()? newKey})
TasksController.service: get TasksService
TasksController.undoDelay: get Duration
TasksController.newKey: get String Function()
TasksController.state: get TasksState
TasksController.load: Future<void>()
TasksController.refresh: Future<void>()
TasksController.setDone: bool(String id, {required bool done})
TasksController.add: bool(String title)
TasksController.retryAdd: bool(String key)
TasksController.discardAdd: bool(String key)
TasksController.update: Future<TaskSaveOutcome>(String id, TaskEdit edit)
TasksController.delete: bool(String id)
TasksController.undo: bool(String id)
TasksController.dispose: void()
TaskDue: final class
TaskDue.new: new(DateTime day, {FlTime? time})
TaskDue.day: get DateTime
TaskDue.time: get FlTime?
TaskDue.operator ==: bool(Object other)
TaskDue.hashCode: get int
Task: final class
Task.new: const new({required String id, required String title, TaskDue? due, FlTaskPriority? priority, bool done})
Task.id: get String
Task.title: get String
Task.due: get TaskDue?
Task.priority: get FlTaskPriority?
Task.done: get bool
Task.withDone: Task(bool done)
Task.withEdit: Task(TaskEdit edit)
Task.operator ==: bool(Object other)
Task.hashCode: get int
TaskEdit: final class
TaskEdit.new: const new({required String title, TaskDue? due, FlTaskPriority? priority})
TaskEdit.title: get String
TaskEdit.due: get TaskDue?
TaskEdit.priority: get FlTaskPriority?
TaskDraft: final class
TaskDraft.new: const new({required String key, required String title})
TaskDraft.key: get String
TaskDraft.title: get String
TasksNoNetwork: final class implements Exception
TasksNoNetwork.new: const new()
TasksService: abstract interface class
TasksService.new: new()
TasksService.tasks: abstract Future<List<Task>>()
TasksService.add: abstract Future<Task>(TaskDraft draft)
TasksService.setDone: abstract Future<void>(String id, {required bool done})
TasksService.update: abstract Future<Task>(String id, TaskEdit edit)
TasksService.delete: abstract Future<void>(String id)
TaskSection: enum {overdue, today, upcoming, someday, done}
TaskSection.overdue: static final TaskSection
TaskSection.today: static final TaskSection
TaskSection.upcoming: static final TaskSection
TaskSection.someday: static final TaskSection
TaskSection.done: static final TaskSection
taskDueIsPast: bool(TaskDue due, DateTime now)
taskSectionOf: TaskSection(Task task, DateTime now)
groupTasks: List<(TaskSection, List<Task>)>(Iterable<Task> tasks, DateTime now)
sampleTasks: List<Task>(DateTime today)
SampleTasksService: final class implements TasksService
SampleTasksService.new: new({required DateTime today, List<Task>? tasks, Duration latency})
SampleTasksService.latency: get Duration
SampleTasksService.tasks: Future<List<Task>>()
SampleTasksService.add: Future<Task>(TaskDraft draft)
SampleTasksService.setDone: Future<void>(String id, {required bool done})
SampleTasksService.update: Future<Task>(String id, TaskEdit edit)
SampleTasksService.delete: Future<void>(String id)
TasksDateFormat: typedef = String Function(DateTime day, Locale locale)
TasksTimeFormat: typedef = String Function(FlTime time, Locale locale)
tasksL10n: const Map<String, Map<String, String>>
TasksStrings: final class
TasksStrings.new: const new(String language, {required DateTime now, TasksDateFormat? formatDate, TasksTimeFormat? formatTime})
TasksStrings.of: factory new(BuildContext context, {required DateTime now, TasksDateFormat? formatDate, TasksTimeFormat? formatTime})
TasksStrings.language: get String
TasksStrings.now: get DateTime
TasksStrings.formatDate: get TasksDateFormat?
TasksStrings.formatTime: get TasksTimeFormat?
TasksStrings.digits: String(int n)
TasksStrings.time: String(FlTime time)
TasksStrings.day: String(DateTime day)
TasksStrings.due: String(TaskDue due)
TasksStrings.separator: get String
TasksStrings.title: get String
TasksStrings.back: get String
TasksStrings.refresh: get String
TasksStrings.loading: get String
TasksStrings.section: String(TaskSection section, int count)
TasksStrings.overdue: get String
TasksStrings.priority: String(FlTaskPriority priority)
TasksStrings.priorityChoice: String(FlTaskPriority? priority)
TasksStrings.edit: String(String title)
TasksStrings.delete: String(String title)
TasksStrings.deleted: String(String title)
TasksStrings.undo: get String
TasksStrings.adding: get String
TasksStrings.notAdded: get String
TasksStrings.retry: get String
TasksStrings.retryAdd: String(String title)
TasksStrings.discard: get String
TasksStrings.discardAdd: String(String title)
TasksStrings.newLabel: get String
TasksStrings.newHint: get String
TasksStrings.add: get String
TasksStrings.added: String(String title)
TasksStrings.marked: String(String title, {required bool done})
TasksStrings.notice: String(TasksNoticeKind kind, String? title)
TasksStrings.emptyTitle: get String
TasksStrings.emptyMessage: get String
TasksStrings.errorTitle: get String
TasksStrings.errorMessage: get String
TasksStrings.offlineTitle: get String
TasksStrings.offlineMessage: get String
TasksStrings.retryLoad: get String
TasksStrings.editTitle: get String
TasksStrings.sheetLabel: get String
TasksStrings.sheetClose: get String
TasksStrings.sheetBarrier: get String
TasksStrings.fieldTitle: get String
TasksStrings.fieldTitleError: get String
TasksStrings.fieldDay: get String
TasksStrings.fieldTime: get String
TasksStrings.fieldTimeHelp: get String
TasksStrings.fieldPriority: get String
TasksStrings.save: get String
TasksStrings.deleteTask: get String
TasksStrings.saveOutcome: String(TaskSaveOutcome outcome)Strings
Every label in English, French and Arabic. The screen follows the closest Localizations; the same table is in the manifest, ready for your ARB files.
| Key | en | fr | ar |
|---|---|---|---|
tasksTitle | Tasks | Tâches | المهام |
tasksBack | Back | Retour | رجوع |
tasksRefresh | Refresh the tasks | Actualiser les tâches | تحديث المهام |
tasksLoading | Loading your tasks | Chargement des tâches | جارٍ تحميل المهام |
tasksSectionOverdue | Overdue | En retard | متأخرة |
tasksSectionToday | Today | Aujourd’hui | اليوم |
tasksSectionUpcoming | Upcoming | À venir | القادمة |
tasksSectionSomeday | No due date | Sans échéance | بلا موعد |
tasksSectionDone | Done | Faites | المنجزة |
tasksSeparator | , | , | ، |
tasksSectionCount | {section} · {count} | {section} · {count} | {section} · {count} |
tasksOverdue | Overdue | En retard | متأخرة |
tasksToday | Today | Aujourd’hui | اليوم |
tasksTomorrow | Tomorrow | Demain | غدًا |
tasksYesterday | Yesterday | Hier | أمس |
tasksDate | {weekday}, {month} {day} | {weekday} {day} {month} | {weekday} {day} {month} |
tasksDateYear | {month} {day}, {year} | {day} {month} {year} | {day} {month} {year} |
tasksDueAt | {day} · {time} | {day} · {time} | {day} · {time} |
tasksMonths | January,February,March,April,May,June,July,August,September,October,November,December | janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre | يناير,فبراير,مارس,أبريل,مايو,يونيو,يوليو,أغسطس,سبتمبر,أكتوبر,نوفمبر,ديسمبر |
tasksWeekdays | Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday | lundi,mardi,mercredi,jeudi,vendredi,samedi,dimanche | الاثنين,الثلاثاء,الأربعاء,الخميس,الجمعة,السبت,الأحد |
tasksHours12 | true | false | false |
tasksAm | AM | AM | ص |
tasksPm | PM | PM | م |
tasksPriorityLow | Low priority | Priorité basse | أولوية منخفضة |
tasksPriorityMedium | Medium priority | Priorité moyenne | أولوية متوسطة |
tasksPriorityHigh | High priority | Priorité haute | أولوية عالية |
tasksEdit | Edit “{title}” | Modifier « {title} » | تعديل «{title}» |
tasksDelete | Delete “{title}” | Supprimer « {title} » | حذف «{title}» |
tasksDeleted | “{title}” deleted | « {title} » supprimée | حُذفت «{title}» |
tasksUndo | Undo | Annuler | تراجع |
tasksAdding | Adding… | Ajout… | جارٍ الإضافة… |
tasksNotAdded | Not added | Non ajoutée | لم تُضف |
tasksRetry | Try again | Réessayer | أعد المحاولة |
tasksRetryAdd | Try adding “{title}” again | Réessayer d’ajouter « {title} » | أعد محاولة إضافة «{title}» |
tasksDiscard | Remove | Retirer | إزالة |
tasksDiscardAdd | Remove “{title}” | Retirer « {title} » | إزالة «{title}» |
tasksNewLabel | New task | Nouvelle tâche | مهمة جديدة |
tasksNewHint | What needs doing? | Que faut-il faire ? | ما الذي يجب إنجازه؟ |
tasksAdd | Add | Ajouter | إضافة |
tasksAdded | “{title}” added | « {title} » ajoutée | أُضيفت «{title}» |
tasksMarkedDone | “{title}” done | « {title} » faite | أُنجزت «{title}» |
tasksMarkedTodo | “{title}” to do | « {title} » à faire | «{title}» غير منجزة |
tasksDoneFailed | “{title}” could not be saved. It is back as it was. | « {title} » n’a pas pu être enregistrée. Elle est revenue comme avant. | تعذّر حفظ «{title}». عادت كما كانت. |
tasksAddFailed | “{title}” could not be added. | « {title} » n’a pas pu être ajoutée. | تعذّرت إضافة «{title}». |
tasksDeleteFailed | “{title}” could not be deleted. It is back in the list. | « {title} » n’a pas pu être supprimée. Elle est revenue dans la liste. | تعذّر حذف «{title}». عادت إلى القائمة. |
tasksRefreshFailed | Your tasks could not refresh. | Les tâches n’ont pas pu se mettre à jour. | تعذّر تحديث المهام. |
tasksRefreshOffline | You are offline. The tasks shown may be out of date. | Vous êtes hors ligne. Les tâches affichées ne sont peut-être pas à jour. | أنت غير متصل. قد لا تكون المهام المعروضة محدّثة. |
tasksEmptyTitle | Nothing to do | Rien à faire | لا شيء لإنجازه |
tasksEmptyMessage | Write your first task below. | Écrivez votre première tâche ci-dessous. | اكتب مهمتك الأولى أدناه. |
tasksErrorTitle | Your tasks could not load | Impossible de charger les tâches | تعذّر تحميل المهام |
tasksErrorMessage | Try again in a moment. | Réessayez dans un instant. | أعد المحاولة بعد قليل. |
tasksOfflineTitle | You are offline | Vous êtes hors ligne | أنت غير متصل |
tasksOfflineMessage | Connect to see your tasks. | Connectez-vous pour voir vos tâches. | اتصل لعرض مهامك. |
tasksEditTitle | Edit task | Modifier la tâche | تعديل المهمة |
tasksSheetLabel | Edit task | Modifier la tâche | تعديل المهمة |
tasksSheetClose | Close | Fermer | إغلاق |
tasksSheetBarrier | Close the editor | Fermer l’édition | إغلاق التعديل |
tasksFieldTitle | Title | Titre | العنوان |
tasksFieldTitleError | Give the task a title. | Donnez un titre à la tâche. | أعطِ المهمة عنوانًا. |
tasksFieldDay | Due date | Échéance | تاريخ الاستحقاق |
tasksFieldTime | Time | Heure | الوقت |
tasksFieldTimeHelp | Choose a due date first. | Choisissez d’abord une échéance. | اختر تاريخ الاستحقاق أولًا. |
tasksFieldPriority | Priority | Priorité | الأولوية |
tasksPriorityNone | None | Aucune | بلا |
tasksPriorityLowShort | Low | Basse | منخفضة |
tasksPriorityMediumShort | Medium | Moyenne | متوسطة |
tasksPriorityHighShort | High | Haute | عالية |
tasksSave | Save | Enregistrer | حفظ |
tasksDeleteTask | Delete task | Supprimer la tâche | حذف المهمة |
tasksSaveFailed | The task could not be saved. Try again. | La tâche n’a pas pu être enregistrée. Réessayez. | تعذّر حفظ المهمة. أعد المحاولة. |
tasksSaveOffline | You are offline. The task is unchanged. | Vous êtes hors ligne. La tâche n’a pas changé. | أنت غير متصل. لم تتغير المهمة. |
tasksSaveMissing | This task no longer exists. | Cette tâche n’existe plus. | هذه المهمة لم تعد موجودة. |
tasksRetryLoad | Try again | Réessayer | أعد المحاولة |
Reference renders
The 16 images published with version 0.2.5, rendered by the shared harness on macOS with Flutter 3.47.7. Each shows every state side by side, at the size of an iPhone (390 × 844) or of an Android phone (412 × 915). fliin verify tasks compares your copy to them.
















Use it to
- toggle a task between done and to do, saved afterwards
- show overdue, today, upcoming and undated tasks in their own groups
- add a new to-do quickly
- edit when a task is due and how urgent it is
- remove a task with a few seconds to bring it back
- hide completed tasks in a folded group
- show a to-do list screen with its sections and a field to add tasks
- Not for
- a single box in a form: use the checkbox (checkbox)
- the events of a day or a week: use the agenda (agenda)
- a single task to check off, with its due date and priority, placed elsewhere: use the task row (task-row)
- States