objectbox / objectbox-dart

Flutter database for super-fast Dart object persistence
https://docs.objectbox.io/getting-started
Apache License 2.0
948 stars 116 forks source link

Strange order void error #497

Closed Sipioteo closed 1 year ago

Sipioteo commented 1 year ago

The error:

When i put "order" function in build query the compiler says This expression has type 'void' and can't be used. but the IDE (VSCode) dosen't show any error and the function has a return.

Basic info:

Dependencies:

Error stack

The error comes form the function "getElementAt" into the invoice.dart file. If i remove the "order" it works, otherwise the compiler shows the error

: Error: This expression has type 'void' and can't be used.
../…/models/invoice.dart:167
    var query = box.query().order(InvoiceDBModel_.order, flags: Order.descending).build();

                            ^
: Error: The method 'build' isn't defined for the class 'void'.
../…/models/invoice.dart:167
Try correcting the name to the name of an existing method, or defining a method named 'build'.
    var query = box.query().order(InvoiceDBModel_.order, flags: Order.descending).build();
                                                                                  ^^^^^

Code

core.dart

import 'package:db/objectbox.g.dart';
import 'package:flutter/material.dart';
import 'package:objectbox_flutter_libs/objectbox_flutter_libs.dart';
export 'package:objectbox/objectbox.dart';
export 'dart:convert';

Store? _store;

abstract class CoreDB<S, T> extends ChangeNotifier {
  CoreDB();

  @protected
  Box<S> get box => _store!.box<S>();

  Store get store => _store!;

  Future<CoreDB<S, T>> init() async {
    _store ??= await openStore(
      directory: '${(await defaultStoreDirectory()).path}_v1'
    );
    reqListener();
    return this;
  }

  void reqListener(){

  }

  @protected
  void initWhatch(Stream stream) {
    stream.listen((event) {
      _wathcLiten();
    });
  }

  void _wathcLiten() {
    notifyListeners();
  }

  T? getById({required String id});

  List<T> getAll();

  void put(T model);

  void putAll(List<T> models);

  void delete(T model);

  void deleteAll() {
    box.removeAll();
  }

  int count() {
    return box.count();
  }

  T? getElementAt(int index);
}

invoice.dart

import 'package:api/models/invoice_model.dart';
import 'package:db/functions.dart';
import 'package:db/models/core.dart';
import 'package:db/objectbox.g.dart';

@Entity()
class InvoiceDBModel {
  @Id(assignable: true)
  int? dbID;

  @Unique(onConflict: ConflictStrategy.replace)
  String? id;

  @Index(type: IndexType.hash)
  String? type;
  double? amount;
  String? currency;
  String? description;
  String? receipt;
  bool? hasATrip;
  String? tripVehicle;
  String? tripModel;
  String? tripType;
  DateTime? tripStart;
  DateTime? tripEnd;

  bool? hasACity;
  double? cityLat;
  double? cityLng;

  double? length;

  int? order;

  InvoiceDBModel({this.type, this.amount, this.currency, this.description, this.receipt, this.tripVehicle, this.tripModel, this.tripType, this.tripStart, this.tripEnd, this.cityLat, this.cityLng, this.length});

  InvoiceDBModel.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    type = json['type'];
    if (json['amount'] != null) {
      amount = json['amount'] + 0.0;
    }

    currency = json['currency'];
    description = json['description'];
    receipt = json['receipt'];
    if (json['trip'] != null) {
      hasATrip = true;
      tripVehicle = json['trip']['vehicle'];
      tripModel = json['trip']['model'];
      tripType = json['trip']['type'];
      tripStart = json['trip']['start'] == null ? null : DateTime.tryParse(json['trip']['start'])?.toLocal();
      tripEnd = json['trip']['end'] == null ? null : DateTime.tryParse(json['trip']['end'])?.toLocal();
      order = tripEnd?.millisecondsSinceEpoch;
    } else {
      hasATrip = false;
    }
    if (json['city'] != null) {
      hasACity = true;
      cityLat = json['city'][0];
      cityLng = json['city'][1];
    } else {
      hasACity = false;
    }
    if (json['length'] != null) {
      length = json['length'] + 0.0;
    }

    dbID = Hash.fastHash(id!);
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['id'] = id;
    data['type'] = type;
    data['amount'] = amount;
    data['currency'] = currency;
    data['description'] = description;
    data['receipt'] = receipt;
    if (hasATrip == true) {
      data['trip'] = <String, dynamic>{};
      data['trip']['vehicle'] = tripVehicle;
      data['trip']['model'] = tripModel;
      data['trip']['type'] = tripType;
      data['trip']['start'] = tripStart?.toUtc().toIso8601String();
      data['trip']['end'] = tripEnd?.toUtc().toIso8601String();
    } else {
      data['trip'] = null;
    }
    if (hasACity == true) {
      data['city'] = <String, dynamic>{};
      data['city'] = [cityLat, cityLng];
    } else {
      data['city'] = null;
    }
    data['length'] = length;
    return data;
  }

  static InvoiceDBModel fromApi(InvoiceModel countryCode) {
    return InvoiceDBModel.fromJson(countryCode.toJson());
  }

  InvoiceModel toApi() {
    return InvoiceModel.fromJson(toJson());
  }
}

class InvoiceDB extends CoreDB<InvoiceDBModel, InvoiceModel> {
  int lenght({String? filterBy}) {
    if (filterBy == null) {
      return box.count();
    } else {
      return box.query(InvoiceDBModel_.type.contains(filterBy)).build().count();
    }
  }

  InvoiceModel? getElementAtByType(int index, {String? filterBy}) {
    Query<InvoiceDBModel> query;
    if (filterBy == null) {
      query = box.query().build();
    } else {
      query = box.query(InvoiceDBModel_.type.contains(filterBy)).build();
    }

    query = box.query().build();
    query.offset = index;
    query.limit = 1;
    return query.findFirst()?.toApi();
  }

  List<InvoiceModel> getAllByType({String? filterBy}) {
    Query<InvoiceDBModel> query;
    if (filterBy == null) {
      query = box.query().build();
    } else {
      if (filterBy == 'trip') {
        query = box.query(InvoiceDBModel_.type.equals(filterBy).and(InvoiceDBModel_.hasATrip.equals(true))).build();
      } else {
        query = box.query(InvoiceDBModel_.type.equals(filterBy)).build();
      }
    }

    return query.find().toList().map((e) => e.toApi()).toList();
  }

  @override
  reqListener() {
    initWhatch(box.query().watch());
  }

  @override
  List<InvoiceModel> getAll() {
    return box.getAll().toList().map((e) => e.toApi()).toList();
  }

  @override
  void delete(InvoiceModel model) {}

  @override
  InvoiceModel? getById({required String id}) {
    return box.query(InvoiceDBModel_.id.equals(id)).build().findFirst()?.toApi();
  }

  @override
  InvoiceModel? getElementAt(int index) {
    var query = box.query().order(InvoiceDBModel_.order, flags: Order.descending).build();
    query.offset = index;
    query.limit = 1;
    return query.findFirst()?.toApi();
  }

  @override
  void put(InvoiceModel model) {
    box.put(InvoiceDBModel.fromApi(model));
  }

  @override
  void putAll(List<InvoiceModel> models) {
    box.removeAll();
    box.putMany(models.map((e) => InvoiceDBModel.fromApi(e)).toList());
  }
}

Expected behavior

Well, it should not behave like that because in the source code the order function HAS a return type.

Sipioteo commented 1 year ago

My bad, there were an error into the pubspec. I was mixting 1.7 with 1.6

greenrobot-team commented 1 year ago

@Sipioteo You can safely only specify a version for the objectbox package and leave the other ObjectBox dependencies at any. Dart will make sure that the correct version is used as the other packages require a single objectbox version.

See https://docs.objectbox.io/getting-started.