Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(neon_framework): migrate to neon_storage #2529

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions packages/neon_framework/example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -881,6 +881,13 @@ packages:
relative: true
source: path
version: "1.0.0"
neon_storage:
dependency: "direct overridden"
description:
path: "../packages/neon_storage"
relative: true
source: path
version: "0.1.0"
nested:
dependency: transitive
description:
Expand Down Expand Up @@ -1337,14 +1344,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "7.0.0"
sqflite:
dependency: transitive
description:
name: sqflite
sha256: a43e5a27235518c03ca238e7b4732cf35eabe863a369ceba6cbefa537a66f16d
url: "https://pub.dev"
source: hosted
version: "2.3.3+1"
Comment on lines -1340 to -1347
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still required for Android/iOS

sqflite_common:
dependency: transitive
description:
Expand Down
4 changes: 3 additions & 1 deletion packages/neon_framework/example/pubspec_overrides.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# melos_managed_dependency_overrides: account_repository,cookie_store,dashboard_app,dynamite_runtime,files_app,interceptor_http_client,neon_framework,neon_http_client,neon_lints,news_app,nextcloud,notes_app,notifications_app,sort_box,talk_app
# melos_managed_dependency_overrides: account_repository,cookie_store,dashboard_app,dynamite_runtime,files_app,interceptor_http_client,neon_framework,neon_http_client,neon_lints,neon_storage,news_app,nextcloud,notes_app,notifications_app,sort_box,talk_app
dependency_overrides:
account_repository:
path: ../packages/account_repository
Expand All @@ -18,6 +18,8 @@ dependency_overrides:
path: ../packages/neon_http_client
neon_lints:
path: ../../neon_lints
neon_storage:
path: ../packages/neon_storage
news_app:
path: ../packages/news_app
nextcloud:
Expand Down
14 changes: 7 additions & 7 deletions packages/neon_framework/lib/neon.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import 'package:neon_framework/src/blocs/push_notifications.dart';
import 'package:neon_framework/src/models/app_implementation.dart';
import 'package:neon_framework/src/models/disposable.dart';
import 'package:neon_framework/src/platform/platform.dart';
import 'package:neon_framework/src/storage/keys.dart';
import 'package:neon_framework/src/theme/neon.dart';
import 'package:neon_framework/src/utils/global_options.dart';
import 'package:neon_framework/src/utils/provider.dart';
Expand Down Expand Up @@ -53,23 +52,24 @@ Future<void> runNeon({
tz.setLocalLocation(location);
}

await NeonStorage().init();
final accountStorage = AccountStorage();
await NeonStorage().init(
dataTables: [
accountStorage,
],
);

final packageInfo = await PackageInfo.fromPlatform();

final globalOptions = GlobalOptions(
packageInfo,
);

final accountStorage = AccountStorage(
accountsPersistence: NeonStorage().singleValueStore(StorageKeys.accounts),
lastAccountPersistence: NeonStorage().singleValueStore(StorageKeys.lastUsedAccount),
);

final accountRepository = AccountRepository(
userAgent: buildUserAgent(packageInfo, theme.branding.name),
httpClient: httpClient ?? http.Client(),
storage: accountStorage,
enableCookieStore: !kIsWeb,
);

await accountRepository.loadAccounts(
Expand Down
1 change: 0 additions & 1 deletion packages/neon_framework/lib/src/blocs/accounts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import 'package:neon_framework/src/blocs/maintenance_mode.dart';
import 'package:neon_framework/src/blocs/unified_search.dart';
import 'package:neon_framework/src/models/account_cache.dart';
import 'package:neon_framework/src/models/disposable.dart';
import 'package:neon_framework/src/storage/keys.dart';
import 'package:neon_framework/src/utils/account_options.dart';
import 'package:neon_framework/storage.dart';
import 'package:rxdart/rxdart.dart';
Expand Down
1 change: 0 additions & 1 deletion packages/neon_framework/lib/src/blocs/first_launch.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import 'package:logging/logging.dart';
import 'package:meta/meta.dart';
import 'package:neon_framework/src/bloc/bloc.dart';
import 'package:neon_framework/src/models/disposable.dart';
import 'package:neon_framework/src/storage/keys.dart';
import 'package:neon_framework/storage.dart';
import 'package:rxdart/rxdart.dart';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import 'package:logging/logging.dart';
import 'package:meta/meta.dart';
import 'package:neon_framework/src/bloc/bloc.dart';
import 'package:neon_framework/src/platform/platform.dart';
import 'package:neon_framework/src/storage/keys.dart';
import 'package:neon_framework/src/utils/global_options.dart';
import 'package:neon_framework/src/utils/push_utils.dart';
import 'package:neon_framework/storage.dart';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import 'package:neon_framework/src/bloc/bloc.dart';
import 'package:neon_framework/src/models/account_cache.dart';
import 'package:neon_framework/src/models/disposable.dart';
import 'package:neon_framework/src/settings/models/options_collection.dart';
import 'package:neon_framework/src/storage/keys.dart';
import 'package:neon_framework/src/utils/findable.dart';
import 'package:neon_framework/src/utils/provider.dart';
import 'package:neon_framework/src/widgets/drawer_destination.dart';
Expand Down
6 changes: 1 addition & 5 deletions packages/neon_framework/lib/src/platform/linux.dart
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does it work without the platform specific initialization?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The neon_storage package handles this with a conditional import/export.

export 'database_factory.dart'
if (dart.library.js_interop) '_browser_database_factory.dart'
if (dart.library.io) '_io_database_factory.dart';

We can not easily run the neon_storage tests on web but I'll verify again that this actually works.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import 'dart:typed_data';
import 'package:file_picker/file_picker.dart';
import 'package:meta/meta.dart';
import 'package:neon_framework/src/platform/platform.dart';
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
import 'package:universal_io/io.dart';

/// Linux specific platform information.
Expand Down Expand Up @@ -43,10 +42,7 @@ class LinuxNeonPlatform implements NeonPlatform {
bool get canUsePaths => true;

@override
void init() {
sqfliteFfiInit();
databaseFactory = databaseFactoryFfi;
}
void init() {}

@override
Future<void> saveFileWithPickDialog(String fileName, String mimeType, Uint8List data) async {
Expand Down
6 changes: 1 addition & 5 deletions packages/neon_framework/lib/src/platform/web.dart
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here?

Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import 'dart:typed_data';

import 'package:meta/meta.dart';
import 'package:neon_framework/src/platform/platform.dart';
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart';
import 'package:web/web.dart';

@immutable
Expand Down Expand Up @@ -39,9 +37,7 @@ class WebNeonPlatform implements NeonPlatform {
bool get canUsePaths => false;

@override
Future<void> init() async {
databaseFactory = databaseFactoryFfiWeb;
}
void init() {}

@override
Future<String?> saveFileWithPickDialog(String fileName, String mimeType, Uint8List data) async {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import 'package:neon_framework/models.dart';
import 'package:neon_framework/src/blocs/accounts.dart';
import 'package:neon_framework/src/settings/models/exportable.dart';
import 'package:neon_framework/src/settings/models/option.dart';
import 'package:neon_framework/src/storage/keys.dart';
import 'package:neon_framework/src/utils/findable.dart';
import 'package:neon_framework/storage.dart';

/// Helper class to export all [Option]s.
///
Expand Down
48 changes: 48 additions & 0 deletions packages/neon_framework/lib/src/storage/neon_cache_db.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:neon_storage/neon_sqlite.dart';
import 'package:neon_storage/neon_storage.dart';

import 'package:path_provider/path_provider.dart';

/// Database holding the neon cache.
final class NeonCacheDB extends MultiTableDatabase {
/// Creates a new database with the given [tables].
factory NeonCacheDB({
Iterable<Table>? tables,
}) {
return NeonCacheDB._(
tables: [
...?tables,
if (!kIsWeb) SQLiteRequestCache.table,
if (!kIsWeb) SQLiteCookiePersistence.table,
],
);
}

NeonCacheDB._({
required super.tables,
});

@override
String get name => 'cache';

@override
Future<String> get path async {
final cacheDir = await getApplicationCacheDirectory();

return buildDatabasePath(cacheDir.path, name);
}

/// The current request cache if available.
RequestCache? get requestCache {
if (kIsWeb) {
return null;
}

assertInitialized();

return const SQLiteRequestCache();
}
}
34 changes: 34 additions & 0 deletions packages/neon_framework/lib/src/storage/neon_data_db.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import 'dart:async';

import 'package:neon_storage/neon_sqlite.dart';
import 'package:neon_storage/neon_storage.dart';
import 'package:path_provider/path_provider.dart';

/// Database holding the neon data.
final class NeonDataDB extends MultiTableDatabase {
/// Creates a new database with the given [tables].
factory NeonDataDB({
Iterable<Table>? tables,
}) {
return NeonDataDB._(
tables: [
...?tables,
SQLiteCachedPersistence.table,
],
);
}

NeonDataDB._({
required super.tables,
});

@override
String get name => 'preferences';

@override
Future<String> get path async {
final cacheDir = await getApplicationSupportDirectory();

return buildDatabasePath(cacheDir.path, name);
}
}
36 changes: 1 addition & 35 deletions packages/neon_framework/lib/src/storage/settings_store.dart
Original file line number Diff line number Diff line change
@@ -1,41 +1,7 @@
// ignore_for_file: avoid_positional_boolean_parameters

import 'package:meta/meta.dart';
import 'package:neon_framework/src/storage/persistence.dart';

/// A storage that can save a group of values primarily used by `Option`s.
///
/// Mimics a subset of the `SharedPreferences` interface to synchronously
/// access data while persisting changes in the background.
///
/// See:
/// * `NeonStorage` to initialize and manage different storage backends.
abstract interface class SettingsStore {
/// The id that uniquely identifies this app storage.
///
/// Used in `Exportable` classes.
String get id;

/// Reads a value from persistent storage, throwing an `Exception` if it is
/// not a `String`.
String? getString(String key);

/// Saves a `String` [value] to persistent storage in the background.
Future<bool> setString(String key, String value);

/// Reads a value from persistent storage, throwing an `Exception` if it is
/// not a `bool`.
bool? getBool(String key);

/// Saves a `bool` [value] to persistent storage in the background.
Future<bool> setBool(String key, bool value);

/// Removes an entry from persistent storage.
Future<bool> remove(String key);

/// Returns all keys in the persistent storage.
List<String> keys();
}
import 'package:neon_framework/src/storage/storage.dart';

/// Default implementation of the [SettingsStore] backed by the given [persistence].
@immutable
Expand Down
42 changes: 1 addition & 41 deletions packages/neon_framework/lib/src/storage/single_value_store.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,7 @@

import 'package:built_collection/built_collection.dart';
import 'package:meta/meta.dart';
import 'package:neon_framework/src/storage/keys.dart';
import 'package:neon_framework/src/storage/persistence.dart';

/// A storage that itself is a single entry of a key value store.
///
/// Mimics a subset of the `SharedPreferences` interface to synchronously
/// access a single value while persisting changes in the background.
///
/// See:
/// * `NeonStorage` to initialize and manage different storage backends.
abstract interface class SingleValueStore {
/// The key used by the storage backend.
StorageKeys get key;

/// Returns true if the persistent storage contains a value at the given [key].
bool hasValue();

/// Reads a value from persistent storage, throwing an `Exception` if it is
/// not a `String`.
String? getString();

/// Saves a `String` [value] to persistent storage in the background.
Future<bool> setString(String value);

/// Reads a value from persistent storage, throwing an `Exception` if it is
/// not a `bool`.
bool? getBool();

/// Saves a `bool` [value] to persistent storage in the background.
Future<bool> setBool(bool value);

/// Removes an entry from persistent storage.
Future<bool> remove();

/// Reads a set of string values from persistent storage, throwing an
/// `Exception` if it's not a `String` collection.
BuiltList<String>? getStringList();

/// Saves a list of strings [value] to persistent storage in the background.
Future<bool> setStringList(BuiltList<String> value);
}
import 'package:neon_framework/src/storage/storage.dart';

/// Default implementation of the [SingleValueStore] backed by the given [persistence].
@immutable
Expand Down
7 changes: 7 additions & 0 deletions packages/neon_framework/lib/src/storage/storage.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export 'package:neon_framework/src/storage/neon_cache_db.dart';
export 'package:neon_framework/src/storage/neon_data_db.dart';
export 'package:neon_framework/src/storage/settings_store.dart';
export 'package:neon_framework/src/storage/single_value_store.dart';
export 'package:neon_framework/src/storage/storage_keys.dart';
export 'package:neon_framework/src/storage/storage_manager.dart';
export 'package:neon_framework/storage.dart';
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
import 'package:meta/meta.dart';

/// Interface of a storable element.
///
/// Usually used in enhanced enums to ensure uniqueness of the storage keys.
abstract interface class Storable {
/// The key of this storage element.
String get value;
}
import 'package:neon_framework/src/storage/storage.dart';

/// Unique storage keys.
///
/// Required by the users of the `NeonStorage` storage backend.
@internal
enum StorageKeys implements Storable {
/// The key for the `AppImplementation`s.
apps._('app'),
Expand Down
Loading