Skip to content

Commit

Permalink
Changed TypeConverters priority. Exist TypeConverter performs first, … (
Browse files Browse the repository at this point in the history
#740)

* Changed TypeConverters priority. Exist TypeConverter performs first, even the column/model field type is a supported SQL type.

* Update CI dart support version.
  • Loading branch information
dkaera authored Apr 18, 2023
1 parent ae4b2c8 commit bb74673
Show file tree
Hide file tree
Showing 18 changed files with 714 additions and 400 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
timeout-minutes: 10

container:
image: dart:2.18.3
image: dart:2.19.3

steps:
- name: Check out code
Expand All @@ -35,7 +35,7 @@ jobs:
timeout-minutes: 10

container:
image: dart:2.18.3
image: dart:2.19.3

steps:
- name: Check out code
Expand Down
2 changes: 1 addition & 1 deletion example/lib/database.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import 'package:sqflite/sqflite.dart' as sqflite;
part 'database.g.dart';

@Database(version: 1, entities: [Task])
@TypeConverters([DateTimeConverter])
@TypeConverters([DateTimeConverter, TaskTypeConverter])
abstract class FlutterDatabase extends FloorDatabase {
TaskDao get taskDao;
}
38 changes: 27 additions & 11 deletions example/lib/database.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 14 additions & 11 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class TasksWidget extends StatefulWidget {
}

class TasksWidgetState extends State<TasksWidget> {
TaskType? _selectedType;
TaskStatus? _selectedType;

@override
Widget build(BuildContext context) {
Expand All @@ -65,7 +65,8 @@ class TasksWidgetState extends State<TasksWidget> {
PopupMenuButton<int>(
itemBuilder: (context) {
return List.generate(
TaskType.values.length + 1, //Uses increment to handle All types
TaskStatus.values.length +
1, //Uses increment to handle All types
(index) {
return PopupMenuItem<int>(
value: index,
Expand Down Expand Up @@ -98,12 +99,12 @@ class TasksWidgetState extends State<TasksWidget> {
);
}

TaskType _getMenuType(int index) => TaskType.values[index - 1];
TaskStatus _getMenuType(int index) => TaskStatus.values[index - 1];
}

class TasksListView extends StatelessWidget {
final TaskDao dao;
final TaskType? selectedType;
final TaskStatus? selectedType;

const TasksListView({
Key? key,
Expand All @@ -117,7 +118,7 @@ class TasksListView extends StatelessWidget {
child: StreamBuilder<List<Task>>(
stream: selectedType == null
? dao.findAllTasksAsStream()
: dao.findAllTasksByTypeAsStream(selectedType!),
: dao.findAllTasksByStatusAsStream(selectedType!),
builder: (_, snapshot) {
if (!snapshot.hasData) return Container();

Expand Down Expand Up @@ -177,7 +178,7 @@ class TaskListCell extends StatelessWidget {
direction: DismissDirection.horizontal,
child: ListTile(
title: Text(task.message),
subtitle: Text('Status: ${task.typeTitle}'),
subtitle: Text('Status: ${task.statusTitle}'),
trailing: Text(task.timestamp.toIso8601String()),
),
confirmDismiss: (direction) async {
Expand All @@ -188,11 +189,13 @@ class TaskListCell extends StatelessWidget {
statusMessage = 'Removed task';
break;
case DismissDirection.startToEnd:
final tasksLength = TaskType.values.length;
final nextIndex = (tasksLength + task.typeIndex + 1) % tasksLength;
final taskCopy = task.copyWith(type: TaskType.values[nextIndex]);
final tasksLength = TaskStatus.values.length;
final nextIndex =
(tasksLength + task.statusIndex + 1) % tasksLength;
final taskCopy =
task.copyWith(status: TaskStatus.values[nextIndex]);
await dao.updateTask(taskCopy);
statusMessage = 'Updated task status by: ${taskCopy.typeTitle}';
statusMessage = 'Updated task status by: ${taskCopy.statusTitle}';
break;
default:
break;
Expand Down Expand Up @@ -261,7 +264,7 @@ class TasksTextField extends StatelessWidget {
if (message.trim().isEmpty) {
_textEditingController.clear();
} else {
final task = Task.optional(message: message);
final task = Task.optional(message: message, type: TaskType.task);
await dao.insertTask(task);
_textEditingController.clear();
}
Expand Down
35 changes: 30 additions & 5 deletions example/lib/task.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import 'package:floor/floor.dart';

enum TaskType {
enum TaskStatus {
open('Open'),
inProgress('In Progress'),
done('Done');

final String title;

const TaskStatus(this.title);
}

enum TaskType {
bug('Bug'),
story('Story'),
task('Task');

final String title;

const TaskType(this.title);
}

Expand All @@ -21,42 +31,55 @@ class Task {

final DateTime timestamp;

final TaskStatus? status;

final TaskType? type;

Task(this.id, this.isRead, this.message, this.timestamp, this.type);
Task(
this.id,
this.isRead,
this.message,
this.timestamp,
this.status,
this.type,
);

factory Task.optional({
int? id,
DateTime? timestamp,
String? message,
bool? isRead,
TaskStatus? status,
TaskType? type,
}) =>
Task(
id,
isRead ?? false,
message ?? 'empty',
timestamp ?? DateTime.now(),
status,
type,
);

@override
String toString() {
return 'Task{id: $id, message: $message, read: $isRead, timestamp: $timestamp, type: $type}';
return 'Task{id: $id, message: $message, read: $isRead, timestamp: $timestamp, status: $status, type: $type}';
}

Task copyWith({
int? id,
String? message,
bool? isRead,
DateTime? timestamp,
TaskStatus? status,
TaskType? type,
}) {
return Task(
id ?? this.id,
isRead ?? this.isRead,
message ?? this.message,
timestamp ?? this.timestamp,
status ?? this.status,
type ?? this.type,
);
}
Expand All @@ -70,6 +93,7 @@ class Task {
message == other.message &&
isRead == other.isRead &&
timestamp == other.timestamp &&
status == other.status &&
type == other.type;

@override
Expand All @@ -78,11 +102,12 @@ class Task {
message.hashCode ^
isRead.hashCode ^
timestamp.hashCode ^
status.hashCode ^
type.hashCode;
}

extension TaskExtension on Task {
String get typeTitle => type?.title ?? 'Empty';
String get statusTitle => status?.title ?? 'Empty';

int get typeIndex => type?.index ?? 0;
int get statusIndex => status?.index ?? 0;
}
4 changes: 2 additions & 2 deletions example/lib/task_dao.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ abstract class TaskDao {
@Query('SELECT DISTINCT COUNT(message) FROM task')
Stream<int?> findUniqueMessagesCountAsStream();

@Query('SELECT * FROM task WHERE type = :type')
Stream<List<Task>> findAllTasksByTypeAsStream(TaskType type);
@Query('SELECT * FROM task WHERE status = :status')
Stream<List<Task>> findAllTasksByStatusAsStream(TaskStatus status);

@insert
Future<void> insertTask(Task task);
Expand Down
13 changes: 13 additions & 0 deletions example/lib/type_converter.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:example/task.dart';
import 'package:floor/floor.dart';

class DateTimeConverter extends TypeConverter<DateTime, int> {
Expand All @@ -11,3 +12,15 @@ class DateTimeConverter extends TypeConverter<DateTime, int> {
return value.millisecondsSinceEpoch;
}
}

class TaskTypeConverter extends TypeConverter<TaskType?, String?> {
@override
TaskType? decode(String? databaseValue) {
return databaseValue == null ? null : TaskType.values.byName(databaseValue);
}

@override
String? encode(TaskType? value) {
return value?.name;
}
}
Loading

0 comments on commit bb74673

Please sign in to comment.