Skip to content

Commit

Permalink
Added documentation to all remaining public members & improved existi…
Browse files Browse the repository at this point in the history
…ng documentation

Refactored `RateLimitedStream` into extension method
Renamed `TilesCounter` & `TilesGenerator` to `TileCounters` & `TileGenerators`
Removed unnecessary permissions from Android example app
  • Loading branch information
JaffaKetchup committed Mar 17, 2024
1 parent 6769e96 commit b31b096
Show file tree
Hide file tree
Showing 26 changed files with 294 additions and 152 deletions.
4 changes: 1 addition & 3 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,4 @@ analyzer:

linter:
rules:
avoid_slow_async_io: false
# TODO: Remove
public_member_api_docs: false
avoid_slow_async_io: false
6 changes: 0 additions & 6 deletions example/android/app/src/debug/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="dev.jaffaketchup.fmtc.demo">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
Expand Down
6 changes: 0 additions & 6 deletions example/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="dev.jaffaketchup.fmtc.demo">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<application
android:label="FMTC Demo"
android:icon="@mipmap/ic_launcher">
Expand Down
6 changes: 0 additions & 6 deletions example/android/app/src/profile/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="dev.jaffaketchup.fmtc.demo">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
Expand Down
2 changes: 2 additions & 0 deletions lib/src/backend/errors/basic.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ final class RootAlreadyInitialised extends FMTCBackendError {
/// Indicates that the specified store structure was not available for use in
/// operations, likely because it didn't exist
final class StoreNotExists extends FMTCBackendError {
/// Indicates that the specified store structure was not available for use in
/// operations, likely because it didn't exist
StoreNotExists({required this.storeName});

/// The referenced store name
Expand Down
15 changes: 15 additions & 0 deletions lib/src/backend/errors/import_export.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ base class ImportExportError extends FMTCBackendError {}
/// Indicates that the specified path to import from or export to did exist, but
/// was not a file
final class ImportExportPathNotFile extends ImportExportError {
/// Indicates that the specified path to import from or export to did exist, but
/// was not a file
ImportExportPathNotFile();

@override
Expand All @@ -20,6 +22,8 @@ final class ImportExportPathNotFile extends ImportExportError {

/// Indicates that the specified file to import did not exist/could not be found
final class ImportPathNotExists extends ImportExportError {
/// Indicates that the specified path to import from or export to did exist, but
/// was not a file
ImportPathNotExists({required this.path});

/// The specified path to the import file
Expand All @@ -36,6 +40,11 @@ final class ImportPathNotExists extends ImportExportError {
/// ("**FMTC")
/// * did not contain all required header information within the file
final class ImportFileNotFMTCStandard extends ImportExportError {
/// Indicates that the import file was not of the expected standard, because it
/// either:
/// * did not contain the appropriate footer signature: hex "FF FF 46 4D 54 43"
/// ("**FMTC")
/// * did not contain all required header information within the file
ImportFileNotFMTCStandard();

@override
Expand All @@ -51,6 +60,12 @@ final class ImportFileNotFMTCStandard extends ImportExportError {
/// should an identifier (eg. the name) of the exporting backend proceeded by
/// hex "FF FE".
final class ImportFileNotBackendCompatible extends ImportExportError {
/// Indicates that the import file was exported from a different FMTC backend,
/// and is not compatible with the current backend
///
/// The bytes prior to the header signature (hex "FF FF 46 4D 54 43" ("**FMTC"))
/// should an identifier (eg. the name) of the exporting backend proceeded by
/// hex "FF FE".
ImportFileNotBackendCompatible();

@override
Expand Down
2 changes: 2 additions & 0 deletions lib/src/backend/impls/objectbox/backend/errors.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ base class FMTCObjectBoxBackendError extends FMTCBackendError {}
/// Indicates that an export failed because the specified output path directory
/// was the same as the root directory
final class ExportInRootDirectoryForbidden extends FMTCObjectBoxBackendError {
/// Indicates that an export failed because the specified output path directory
/// was the same as the root directory
ExportInRootDirectoryForbidden();

@override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,6 @@ Future<void> _worker(

query.close();
case _WorkerCmdType.writeTile:
// TODO: Test all
final storeName = cmd.args['storeName']! as String;
final url = cmd.args['url']! as String;
final bytes = cmd.args['bytes'] as Uint8List?;
Expand Down
50 changes: 49 additions & 1 deletion lib/src/backend/impls/objectbox/models/src/recovery.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ import 'package:objectbox/objectbox.dart';

import '../../../../../../flutter_map_tile_caching.dart';

/// Represents a [RecoveredRegion] in ObjectBox
@Entity()
base class ObjectBoxRecovery {
/// Create a raw representation of a [RecoveredRegion] in ObjectBox
///
/// Prefer using [ObjectBoxRecovery.fromRegion].
ObjectBoxRecovery({
required this.refId,
required this.storeName,
Expand All @@ -33,6 +37,8 @@ base class ObjectBoxRecovery {
required this.customPolygonLngs,
});

/// Create a raw representation of a [RecoveredRegion] in ObjectBox from a
/// [DownloadableRegion]
ObjectBoxRecovery.fromRegion({
required this.refId,
required this.storeName,
Expand Down Expand Up @@ -109,41 +115,83 @@ base class ObjectBoxRecovery {
.toList(growable: false)
: null;

/// ObjectBox ID
///
/// Not to be confused with [refId].
@Id()
@internal
int id = 0;

/// Corresponds to [RecoveredRegion.id]
@Index()
@Unique()
int refId;

/// Corresponds to [RecoveredRegion.storeName]
String storeName;

/// The timestamp of when this object was created/stored
@Property(type: PropertyType.date)
DateTime creationTime;

/// Corresponds to [RecoveredRegion.minZoom] & [DownloadableRegion.minZoom]
int minZoom;

/// Corresponds to [RecoveredRegion.maxZoom] & [DownloadableRegion.maxZoom]
int maxZoom;

/// Corresponds to [RecoveredRegion.start] & [DownloadableRegion.start]
int startTile;

/// Corresponds to [RecoveredRegion.end] & [DownloadableRegion.end]
int? endTile;

int typeId; // 0 - rect, 1 - circle, 2 - line, 3 - custom polygon
/// Corresponds to the generic type of [DownloadableRegion]
///
/// Values must be as follows:
/// * 0: rect
/// * 1: circle
/// * 2: line
/// * 3: custom polygon
int typeId;

/// Corresponds to [RecoveredRegion.bounds] ([RectangleRegion.bounds])
double? rectNwLat;

/// Corresponds to [RecoveredRegion.bounds] ([RectangleRegion.bounds])
double? rectNwLng;

/// Corresponds to [RecoveredRegion.bounds] ([RectangleRegion.bounds])
double? rectSeLat;

/// Corresponds to [RecoveredRegion.bounds] ([RectangleRegion.bounds])
double? rectSeLng;

/// Corresponds to [RecoveredRegion.center] ([CircleRegion.center])
double? circleCenterLat;

/// Corresponds to [RecoveredRegion.center] ([CircleRegion.center])
double? circleCenterLng;

/// Corresponds to [RecoveredRegion.radius] ([CircleRegion.radius])
double? circleRadius;

/// Corresponds to [RecoveredRegion.line] ([LineRegion.line])
List<double>? lineLats;

/// Corresponds to [RecoveredRegion.line] ([LineRegion.line])
List<double>? lineLngs;

/// Corresponds to [RecoveredRegion.radius] ([LineRegion.radius])
double? lineRadius;

/// Corresponds to [RecoveredRegion.line] ([CustomPolygonRegion.outline])
List<double>? customPolygonLats;

/// Corresponds to [RecoveredRegion.line] ([CustomPolygonRegion.outline])
List<double>? customPolygonLngs;

/// Convert this object into a [RecoveredRegion]
RecoveredRegion toRegion() => RecoveredRegion(
id: refId,
storeName: storeName,
Expand Down
6 changes: 6 additions & 0 deletions lib/src/backend/impls/objectbox/models/src/root.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,22 @@

import 'package:objectbox/objectbox.dart';

/// Cache for root-level statistics in ObjectBox
@Entity()
class ObjectBoxRoot {
/// Create a new cache for root-level statistics in ObjectBox
ObjectBoxRoot({
required this.length,
required this.size,
});

/// ObjectBox ID
@Id()
int id = 0;

/// Total number of tiles
int length;

/// Total size (in bytes) of all tiles
int size;
}
18 changes: 18 additions & 0 deletions lib/src/backend/impls/objectbox/models/src/store.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ import 'package:objectbox/objectbox.dart';

import 'tile.dart';

/// Cache for store-level statistics & storage for metadata, referenced by
/// unique name, in ObjectBox
@Entity()
class ObjectBoxStore {
/// Create a cache for store-level statistics & storage for metadata,
/// referenced by unique name, in ObjectBox
ObjectBoxStore({
required this.name,
required this.length,
Expand All @@ -16,20 +20,34 @@ class ObjectBoxStore {
required this.metadataJson,
});

/// ObjectBox ID
@Id()
int id = 0;

/// Human-readable name of the store
@Index()
@Unique()
String name;

/// Relation to all tiles that belong to this store
@Index()
@Backlink('stores')
final tiles = ToMany<ObjectBoxTile>();

/// Number of tiles
int length;

/// Size (in bytes) of all tiles
int size;

/// Number of cache hits (successful retrievals) from this store only
int hits;

/// Number of cache misses (unsuccessful retrievals) from this store only
int misses;

/// Storage for metadata in JSON format
///
/// Only supports string-string key-value pairs.
String metadataJson;
}
4 changes: 4 additions & 0 deletions lib/src/backend/impls/objectbox/models/src/tile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ import 'package:objectbox/objectbox.dart';
import '../../../../interfaces/models.dart';
import 'store.dart';

/// ObjectBox-specific implementation of [BackendTile]
@Entity()
base class ObjectBoxTile extends BackendTile {
/// Create an ObjectBox-specific implementation of [BackendTile]
ObjectBoxTile({
required this.url,
required this.bytes,
required this.lastModified,
});

/// ObjectBox ID
@Id()
int id = 0;

Expand All @@ -32,6 +35,7 @@ base class ObjectBoxTile extends BackendTile {
@Property(type: PropertyType.date)
DateTime lastModified;

/// Relation to all stores that this tile belongs to
@Index()
final stores = ToMany<ObjectBoxStore>();
}
23 changes: 11 additions & 12 deletions lib/src/bulk_download/manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ Future<void> _downloadManager(

// Count number of tiles
final maxTiles = input.region.when(
rectangle: TilesCounter.rectangleTiles,
circle: TilesCounter.circleTiles,
line: TilesCounter.lineTiles,
customPolygon: TilesCounter.customPolygonTiles,
rectangle: TileCounters.rectangleTiles,
circle: TileCounters.circleTiles,
line: TileCounters.lineTiles,
customPolygon: TileCounters.customPolygonTiles,
);

// Setup sea tile removal system
Expand Down Expand Up @@ -70,10 +70,10 @@ Future<void> _downloadManager(
final tilereceivePort = ReceivePort();
final tileIsolate = await Isolate.spawn(
input.region.when(
rectangle: (_) => TilesGenerator.rectangleTiles,
circle: (_) => TilesGenerator.circleTiles,
line: (_) => TilesGenerator.lineTiles,
customPolygon: (_) => TilesGenerator.customPolygonTiles,
rectangle: (_) => TileGenerators.rectangleTiles,
circle: (_) => TileGenerators.circleTiles,
line: (_) => TileGenerators.lineTiles,
customPolygon: (_) => TileGenerators.customPolygonTiles,
),
(sendPort: tilereceivePort.sendPort, region: input.region),
onExit: tilereceivePort.sendPort,
Expand All @@ -87,12 +87,11 @@ Future<void> _downloadManager(
final tileQueue = StreamQueue(
input.rateLimit == null
? rawTileStream
: RateLimitedStream.fromSourceStream(
emitEvery: Duration(
: rawTileStream.rateLimit(
minimumSpacing: Duration(
microseconds: ((1 / input.rateLimit!) * 1000000).ceil(),
),
sourceStream: rawTileStream,
).stream,
),
);
final requestTilePort = await tileQueue.next as SendPort;

Expand Down
Loading

0 comments on commit b31b096

Please sign in to comment.