diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 000000000..9033b7b16
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,7 @@
+{
+ "workbench.colorCustomizations": {
+ "activityBar.background": "#0C227B",
+ "titleBar.activeBackground": "#1130AC",
+ "titleBar.activeForeground": "#FCFDFF"
+ }
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index 571d732c7..ebcd1164a 100644
--- a/README.md
+++ b/README.md
@@ -66,8 +66,9 @@ You can alternatively install the build from PlayStore or F-Droid.
3. Pull in all submodules with `git submodule update --init --recursive`
4. Enable repo git hooks `git config core.hooksPath hooks`
5. Setup TensorFlowLite by executing `setup.sh`
-6. For Android, [setup your keystore](https://docs.flutter.dev/deployment/android#create-an-upload-keystore) and run `flutter build apk --release --flavor independent`
-7. For iOS, run `flutter build ios`
+6. If using Visual Studio Code, add the [Flutter Intl](https://marketplace.visualstudio.com/items?itemName=localizely.flutter-intl) extension
+7. For Android, [setup your keystore](https://docs.flutter.dev/deployment/android#create-an-upload-keystore) and run `flutter build apk --release --flavor independent`
+8. For iOS, run `flutter build ios`
## 🙋 Help
diff --git a/lib/core/constants.dart b/lib/core/constants.dart
index 236419b4d..63f62ed39 100644
--- a/lib/core/constants.dart
+++ b/lib/core/constants.dart
@@ -57,3 +57,11 @@ const double restrictedMaxWidth = 430;
const double mobileSmallThreshold = 336;
const publicLinkDeviceLimits = [50, 25, 10, 5, 2, 1];
+
+const kilometersPerDegree = 111.16;
+
+const radiusValues = [2, 10, 20, 40, 80, 200, 400, 1200];
+
+const defaultRadiusValueIndex = 4;
+
+const galleryGridSpacing = 2.0;
diff --git a/lib/db/entities_db.dart b/lib/db/entities_db.dart
new file mode 100644
index 000000000..b8b48fbe4
--- /dev/null
+++ b/lib/db/entities_db.dart
@@ -0,0 +1,65 @@
+import 'package:flutter/foundation.dart';
+import 'package:photos/db/files_db.dart';
+import "package:photos/models/api/entity/type.dart";
+import "package:photos/models/local_entity_data.dart";
+import 'package:sqflite/sqlite_api.dart';
+
+extension EntitiesDB on FilesDB {
+ Future upsertEntities(
+ List data, {
+ ConflictAlgorithm conflictAlgorithm = ConflictAlgorithm.replace,
+ }) async {
+ debugPrint("Inserting missing PathIDToLocalIDMapping");
+ final db = await database;
+ var batch = db.batch();
+ int batchCounter = 0;
+ for (LocalEntityData e in data) {
+ if (batchCounter == 400) {
+ await batch.commit(noResult: true);
+ batch = db.batch();
+ batchCounter = 0;
+ }
+ batch.insert(
+ "entities",
+ e.toJson(),
+ conflictAlgorithm: conflictAlgorithm,
+ );
+ batchCounter++;
+ }
+ await batch.commit(noResult: true);
+ }
+
+ Future deleteEntities(
+ List ids,
+ ) async {
+ final db = await database;
+ var batch = db.batch();
+ int batchCounter = 0;
+ for (String id in ids) {
+ if (batchCounter == 400) {
+ await batch.commit(noResult: true);
+ batch = db.batch();
+ batchCounter = 0;
+ }
+ batch.delete(
+ "entities",
+ where: "id = ?",
+ whereArgs: [id],
+ );
+ batchCounter++;
+ }
+ await batch.commit(noResult: true);
+ }
+
+ Future> getEntities(EntityType type) async {
+ final db = await database;
+ final List