Commit df73f5e5 authored by Erfan Jazeb Nikoo's avatar Erfan Jazeb Nikoo Committed by Azat Alimov
Browse files

refactor-project-structure

parent abf61baa
Showing with 151 additions and 162 deletions
+151 -162
......@@ -4,6 +4,12 @@ The flutter application is the frontend for the Memri [pod](https://gitlab.memri
## Try it out
The pre-alpha version of the Memri frontend is freely available at [memri.docs.memri.io/flutter-app](https://memri.docs.memri.io/flutter-app/#/), and can be used by connecting to your local pod or the public memri hosted pod (alpha) at [dev.pod.memri.io](https://dev.pod.memri.io/). Regardless of your setup: only you have access to the data in your pod. After first login, your credentials will be stored locally for re-use when you revisit the app. To create a new account after first login, [delete your browser database](https://stackoverflow.com/questions/9384128/how-to-delete-indexeddb#answer-9389289) or connect from an incognito tab (in this case your data will be lost after closing the tab). Note that this is a very early release, for help or questions reach out on [Discord]("https://discord.com/invite/BcRfajJk4k").
## How to generate models?
```
flutter pub run build_runner watch --delete-conflicting-outputs
```
## Build & Run (Flutter-web)
To build the Memri flutter-app locally, you need to either install the Flutter environment locally, or use the docker build. Currently the app is tested and built for flutter web.
......
......@@ -59,11 +59,12 @@
{
"_type": "Plugin",
"pluginType": "app",
"name": "Sentiment analysis app",
"containerImage": "gitlab.memri.io:5050/memri/plugins/sentiment-analysis:prod-latest",
"pluginModule": "sentiment_analysis",
"pluginName": "SentimentAnalysis",
"pluginDescription": "Sentiment analysis app categorizes pieces of writing as positive, neutral, or negative based on emotional tone they carry. It uses natural language processing and machine learning techniques to produce quantitative results."
"name": "Sentiment Plugin",
"containerImage": "gitlab.memri.io:5050/eelcovdw/sentiment_plugin:dev-latest",
"pluginModule": "sentiment_plugin.plugin",
"pluginName": "ClassifierPlugin",
"pluginDescription": "A transformer based sentiment analyis plugin",
"configJson": "[{\"name\":\"item_type\",\"display\":\"Item Type\",\"data_type\":\"Text\",\"type\":\"textbox\",\"default\":null,\"optional\":true},{\"name\":\"item_service\",\"display\":\"Item Service\",\"data_type\":\"Text\",\"type\":\"textbox\",\"default\":null,\"optional\":true},{\"name\":\"model_name\",\"display\":\"Model Name\",\"data_type\":\"Text\",\"type\":\"textbox\",\"default\":\"cardiffnlp/twitter-xlm-roberta-base-sentiment\",\"optional\":true},{\"name\":\"model_version\",\"display\":\"Model Version\",\"data_type\":\"Text\",\"type\":\"textbox\",\"default\":\"0.1\",\"optional\":true}]"
},
{
"_type": "Plugin",
......
export 'Authentication_web.dart' if (dart.library.io) 'Authentication_mobile.dart';
export 'FileStorageController_mobile.dart' if (dart.library.html) 'FileStorageController_web.dart';
//
// MainView.swift
// memri
//
// Created by T Brennan on 7/12/20.
// Copyright © 2020 memri. All rights reserved.
//
import 'package:flutter/material.dart';
import 'package:memri/MemriApp/Controllers/API/Authentication_shared.dart';
import 'package:memri/MemriApp/Controllers/AppController.dart';
import 'package:memri/MemriApp/Controllers/SceneController.dart';
import 'package:memri/MemriApp/UI/Setup/OnboardingStart.dart';
import 'Auth/AuthenticationScreen.dart';
import 'SceneView.dart';
import 'Setup/OnboardingKeys.dart';
import 'package:memri/controllers/app_controller.dart';
import 'package:memri/controllers/scene_controller.dart';
import 'package:memri/core/apis/auth/authentication_shared.dart';
import 'package:memri/screens/authentication_screen.dart';
import 'package:memri/screens/scene_view.dart';
import 'package:memri/screens/setup/onboarding_keys.dart';
import 'package:memri/screens/setup/onboarding_start.dart';
/// This is the view used in each scene to display the appropriate state
/// This depends on whether the app has been setup, and if the user is authenticated.
class MainView extends StatefulWidget {
MainView();
class App extends StatefulWidget {
App();
@override
_MainViewState createState() => _MainViewState();
_AppState createState() => _AppState();
}
class _MainViewState extends State<MainView> {
class _AppState extends State<App> {
final AppController appController = AppController.shared;
late final SceneController sceneController;
late Future<void> _init;
Exception? authError;
_MainViewState();
_AppState();
@override
void initState() {
......
import 'package:flutter/material.dart';
import 'package:memri/constants/cvu/cvu_font.dart';
final ButtonStyle primaryButtonStyle = TextButton.styleFrom(
backgroundColor: Color(0xff333333),
primary: Color(0xffF5F5F5),
textStyle: CVUFont.buttonLabel,
minimumSize: Size.zero,
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
padding: const EdgeInsets.all(10),
);
final Map<String, ButtonStyle> buttonStyles = {"primaryButton": primaryButtonStyle};
import 'package:flutter/material.dart';
import 'package:memri/MemriApp/UI/CVUComponents/types/CVUFont.dart';
import 'package:memri/constants/cvu/cvu_font.dart';
final lightTheme = ThemeData(
fontFamily: 'Karla',
......@@ -26,14 +26,3 @@ final lightTheme = ThemeData(
TargetPlatform.android: FadeUpwardsPageTransitionsBuilder(),
}),
);
final primaryButtonStyle = TextButton.styleFrom(
backgroundColor: Color(0xff333333),
primary: Color(0xffF5F5F5),
textStyle: CVUFont.buttonLabel,
minimumSize: Size.zero,
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
padding: const EdgeInsets.all(10),
);
final Map<String, ButtonStyle> buttonStyles = {"primaryButton": primaryButtonStyle};
import 'package:flutter_contact/contacts.dart';
import 'package:memri/MemriApp/Controllers/AppController.dart';
import 'package:memri/MemriApp/Controllers/Database/DatabaseController.dart';
import 'package:memri/MemriApp/Controllers/Database/ItemEdgeRecord.dart';
import 'package:memri/MemriApp/Controllers/Database/ItemRecord.dart';
import 'package:memri/MemriApp/Controllers/Database/PropertyDatabaseValue.dart';
import 'package:memri/MemriApp/Model/Database.dart';
import 'package:memri/controllers/app_controller.dart';
import 'package:memri/controllers/database_controller.dart';
import 'package:memri/controllers/file_storage/file_storage_controller.dart';
import 'package:memri/core/services/database/property_database_value.dart';
import 'package:memri/models/database/database.dart';
import 'package:memri/models/database/item_edge_record.dart';
import 'package:memri/models/database/item_record.dart';
import 'package:moor/moor.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:phone_number/phone_number.dart' as Phone;
import 'package:uuid/uuid.dart';
import 'FileStorageController_shared.dart';
class AddressBookController {
static bool syncing = false;
......
//
// AppController.swift
// MemriDatabase
//
// Created by T Brennan on 14/12/20.
//
import 'dart:async';
import 'dart:isolate';
import 'package:flutter/foundation.dart';
import 'package:memri/MemriApp/CVU/CVUController.dart';
import 'package:memri/MemriApp/Controllers/FileStorageController_shared.dart';
import 'package:memri/MemriApp/Controllers/SceneController.dart';
import 'package:memri/MemriApp/Controllers/Settings/Settings.dart';
import 'package:memri/controllers/cvu_controller.dart';
import 'package:memri/controllers/database_controller.dart';
import 'package:memri/controllers/file_storage/file_storage_controller.dart';
import 'package:memri/controllers/permission_controller.dart';
import 'package:memri/controllers/pub_sub_controller.dart';
import 'package:memri/controllers/scene_controller.dart';
import 'package:memri/controllers/syncing/sync_controller.dart';
import 'package:memri/controllers/syncing/sync_controller_isolate.dart';
import 'package:memri/core/apis/auth/authentication_shared.dart';
import 'package:memri/core/apis/pod/pod_connection_details.dart';
import 'package:memri/core/services/settings.dart';
import 'package:path_provider/path_provider.dart';
import 'API/Authentication_shared.dart';
import 'API/PodAPIConnectionDetails.dart';
import 'Database/DatabaseController.dart';
import 'PermissionController.dart';
import 'PubSubController.dart';
import 'Syncing/SyncController.dart';
import 'Syncing/SyncController_isolate.dart';
enum AppState { setup, keySaving, authentication, authenticated }
class AppController {
......@@ -31,7 +25,7 @@ class AppController {
late DatabaseController databaseController;
late SyncController syncController;
late CVUController cvuController;
late PubSubController pubsubController;
late PubSubController pubSubController;
late PermissionsController permissionController;
StreamSubscription? syncStream;
bool isDevelopersMode = false;
......@@ -45,7 +39,7 @@ class AppController {
static String keychainDatabaseKey = "memri_databaseKey";
PodAPIConnectionDetails? _podConnectionConfig;
PodConnectionDetails? _podConnectionConfig;
bool isInDemoMode = false;
bool isNewPodSetup = false;
......@@ -53,7 +47,7 @@ class AppController {
databaseController = DatabaseController(inMemory: false);
syncController = SyncController(databaseController);
cvuController = CVUController(databaseController);
pubsubController = PubSubController(databaseController);
pubSubController = PubSubController(databaseController);
permissionController = PermissionsController();
}
......@@ -85,7 +79,7 @@ class AppController {
isInDemoMode = await Settings.shared.get<bool>("defaults/general/isInDemoMode") ?? false;
if (!isInDemoMode) {
PodAPIConnectionDetails connection = (await AppController.shared.podConnectionConfig)!;
PodConnectionDetails connection = (await AppController.shared.podConnectionConfig)!;
var receivePort = ReceivePort();
var documentsDirectory;
if (!kIsWeb) {
......@@ -155,7 +149,7 @@ class AppController {
connectToPod(SetupConfig config, Future Function() callback) async {
if (config is SetupConfigExistingPod) {
var uri = Uri.parse(config.config.podURL);
_podConnectionConfig = PodAPIConnectionDetails(
_podConnectionConfig = PodConnectionDetails(
scheme: uri.scheme,
host: uri.host,
port: uri.port,
......@@ -167,7 +161,7 @@ class AppController {
var keys = await Authentication.createOwnerAndDBKey();
var ownerKey = keys.publicKey;
var databaseKey = keys.dbKey;
_podConnectionConfig = PodAPIConnectionDetails(
_podConnectionConfig = PodConnectionDetails(
scheme: uri.scheme,
host: uri.host,
port: uri.port,
......@@ -217,7 +211,7 @@ class AppController {
}
// MARK: Pod connection
Future<PodAPIConnectionDetails?> get podConnectionConfig async {
Future<PodConnectionDetails?> get podConnectionConfig async {
if (isInDemoMode) return null;
try {
// Here you should retrieve the connection details stored in the database
......@@ -228,7 +222,7 @@ class AppController {
var databaseKey = keys.dbKey;
if (podURL == null) return null;
var uri = Uri.parse(podURL);
_podConnectionConfig = PodAPIConnectionDetails(
_podConnectionConfig = PodConnectionDetails(
scheme: uri.scheme,
host: uri.host,
port: uri.port,
......@@ -256,7 +250,7 @@ class AppController {
await FileStorageController.deleteFileStorage();
await databaseController.delete();
pubsubController.reset();
pubSubController.reset();
cvuController.reset();
await init();
......
//
// CVUController.swift
// MemriDatabase
//
// Created by T Brennan on 7/12/20.
//
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:memri/MemriApp/CVU/parsing/CVULexer.dart';
import 'package:memri/MemriApp/CVU/parsing/CVUParser.dart';
import 'package:memri/MemriApp/CVU/resolving/CVUContext.dart';
import 'package:memri/MemriApp/CVU/resolving/CVULookupController.dart';
import 'package:memri/MemriApp/Controllers/Database/DatabaseController.dart';
import 'package:memri/MemriApp/Controllers/Database/ItemPropertyRecord.dart';
import 'package:memri/MemriApp/Controllers/Database/ItemRecord.dart';
import 'package:memri/MemriApp/Controllers/Database/PropertyDatabaseValue.dart';
import 'package:memri/MemriApp/Controllers/PageController.dart' as memri;
import 'package:memri/MemriApp/Extensions/BaseTypes/Collection.dart';
import 'package:memri/MemriApp/Extensions/BaseTypes/Enum.dart';
import 'package:memri/MemriApp/Extensions/BaseTypes/String.dart';
import 'package:memri/MemriApp/Model/Database.dart';
import 'package:memri/MemriApp/UI/CVUComponents/CVUElementView.dart';
import 'package:memri/MemriApp/UI/CVUComponents/CVUUINodeResolver.dart';
import 'package:memri/MemriApp/UI/UIHelpers/utilities.dart';
import 'definitions/CVUParsedDefinition.dart';
import 'definitions/CVUUINode.dart';
import 'package:memri/controllers/cvu_lookup_controller.dart';
import 'package:memri/controllers/database_controller.dart';
import 'package:memri/controllers/page_controller.dart' as memri;
import 'package:memri/core/cvu/parsing/cvu_parser.dart';
import 'package:memri/core/cvu/resolving/cvu_context.dart';
import 'package:memri/core/services/database/property_database_value.dart';
import 'package:memri/models/cvu/cvu_lexer.dart';
import 'package:memri/models/cvu/cvu_parsed_definition.dart';
import 'package:memri/models/cvu/cvu_ui_node.dart';
import 'package:memri/models/database/database.dart';
import 'package:memri/models/database/item_property_record.dart';
import 'package:memri/models/database/item_record.dart';
import 'package:memri/utils/extensions/collection.dart';
import 'package:memri/utils/extensions/enum.dart';
import 'package:memri/utils/extensions/string.dart';
import 'package:memri/widgets/components/cvu/cvu_element_view.dart';
import 'package:memri/widgets/components/cvu/cvu_ui_node_resolver.dart';
import 'package:memri/widgets/empty.dart';
class CVUController {
late List<CVUParsedDefinition> definitions;
......
import 'dart:convert';
import 'package:html/parser.dart';
import 'package:memri/MemriApp/CVU/definitions/CVUValue.dart';
import 'package:memri/MemriApp/CVU/definitions/CVUValue_Constant.dart';
import 'package:memri/MemriApp/CVU/definitions/CVUValue_Expression.dart';
import 'package:memri/MemriApp/CVU/definitions/CVUValue_LookupNode.dart';
import 'package:memri/MemriApp/Controllers/Database/DatabaseController.dart';
import 'package:memri/MemriApp/Controllers/Database/ItemRecord.dart';
import 'package:memri/MemriApp/Controllers/Database/PropertyDatabaseValue.dart';
import 'package:memri/MemriApp/Controllers/Database/Schema.dart';
import 'package:memri/MemriApp/Helpers/Binding.dart';
import 'package:memri/MemriApp/Extensions/BaseTypes/DateTime.dart';
import 'package:memri/controllers/database_controller.dart';
import 'package:memri/core/cvu/resolving/cvu_context.dart';
import 'package:memri/core/services/database/property_database_value.dart';
import 'package:memri/core/services/database/schema.dart';
import 'package:memri/models/cvu/cvu_value.dart';
import 'package:memri/models/cvu/cvu_value_constant.dart';
import 'package:memri/models/cvu/cvu_value_expression.dart';
import 'package:memri/models/cvu/cvu_value_lookup_node.dart';
import 'package:memri/models/cvu/cvu_view_arguments.dart';
import 'package:memri/models/database/item_record.dart';
import 'package:memri/utils/binding.dart';
import 'package:memri/utils/extensions/collection.dart';
import 'package:memri/utils/extensions/date_time.dart';
import 'package:memri/utils/extensions/number.dart';
import 'package:memri/utils/extensions/string.dart';
import 'package:moor/moor.dart';
import 'CVUContext.dart';
import 'CVUViewArguments.dart';
import 'package:memri/MemriApp/Extensions/BaseTypes/String.dart';
import 'package:memri/MemriApp/Extensions/BaseTypes/Collection.dart';
import 'package:memri/MemriApp/Extensions/BaseTypes/Number.dart';
/// This struct can be used to _resolve CVU values to a final value of the desired type.
/// For lookups you must provide a CVUContext which contains required information on the default item, viewArguments, etc to be used in the lookup.
......
import 'package:flutter/foundation.dart';
import 'package:memri/MemriApp/Controllers/Database/ItemRecord.dart';
import 'package:memri/MemriApp/Model/Database.dart';
import 'package:memri/core/services/database/demo_data.dart';
import 'package:memri/core/services/database/schema.dart';
import 'package:memri/core/services/database/shared.dart';
import 'package:memri/models/database/database.dart';
import 'package:memri/models/database/item_record.dart';
import 'package:memri/utils/extensions/collection.dart';
import 'package:memri/utils/extensions/string.dart';
import 'package:moor/isolate.dart';
import 'package:moor/moor.dart';
import 'DemoData.dart';
import 'Schema.dart';
import 'package:memri/MemriApp/Extensions/BaseTypes/String.dart';
import 'package:memri/MemriApp/Extensions/BaseTypes/Collection.dart';
/// The database controller provides access to the app's SQLite database. Generally only a single database controller will be used throughout the app
class DatabaseController {
......
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:memri/MemriApp/CVU/definitions/CVUParsedDefinition.dart';
import 'package:memri/MemriApp/CVU/definitions/CVUValue.dart';
import 'package:memri/MemriApp/CVU/definitions/CVUValue_Constant.dart';
import 'package:memri/MemriApp/CVU/resolving/CVUContext.dart';
import 'package:memri/MemriApp/CVU/resolving/CVULookupController.dart';
import 'package:memri/MemriApp/CVU/resolving/CVUPropertyResolver.dart';
import 'package:memri/MemriApp/Controllers/AppController.dart';
import 'package:memri/MemriApp/Controllers/Database/DatabaseController.dart';
import 'package:memri/MemriApp/Controllers/Database/PropertyDatabaseValue.dart';
import 'package:memri/MemriApp/Model/Database.dart';
import 'package:moor/moor.dart';
import 'ItemRecord.dart';
import 'Schema.dart';
import 'package:json_annotation/json_annotation.dart' as annotation;
import 'package:memri/MemriApp/Extensions/BaseTypes/String.dart';
import 'package:memri/MemriApp/Extensions/BaseTypes/Collection.dart';
import 'package:memri/controllers/app_controller.dart';
import 'package:memri/controllers/cvu_lookup_controller.dart';
import 'package:memri/controllers/database_controller.dart';
import 'package:memri/core/cvu/resolving/cvu_context.dart';
import 'package:memri/core/cvu/resolving/cvu_property_resolver.dart';
import 'package:memri/core/services/database/property_database_value.dart';
import 'package:memri/core/services/database/schema.dart';
import 'package:memri/models/cvu/cvu_parsed_definition.dart';
import 'package:memri/models/cvu/cvu_value.dart';
import 'package:memri/models/cvu/cvu_value_constant.dart';
import 'package:memri/models/database/database.dart';
import 'package:memri/models/database/item_record.dart';
import 'package:memri/utils/extensions/collection.dart';
import 'package:memri/utils/extensions/string.dart';
import 'package:moor/moor.dart';
part 'DatabaseQuery.g.dart';
part 'database_query.g.dart';
enum ConditionOperator { and, or }
/// This type is used to describe a database query.
@annotation.JsonSerializable()
@JsonSerializable()
class DatabaseQueryConfig extends ChangeNotifier with EquatableMixin {
/// A list of item types to include. Default is Empty -> ALL item types
List<String> itemTypes;
......@@ -682,7 +681,7 @@ class DatabaseQueryConfig extends ChangeNotifier with EquatableMixin {
];
}
@annotation.JsonSerializable()
@JsonSerializable()
class JoinQueryStruct {
String table;
String joinQuery;
......@@ -717,7 +716,7 @@ abstract class DatabaseQueryCondition {
}
// A property of this item equals a particular value
@annotation.JsonSerializable()
@JsonSerializable()
class DatabaseQueryConditionPropertyEquals extends DatabaseQueryCondition {
PropertyEquals value;
......@@ -731,7 +730,7 @@ class DatabaseQueryConditionPropertyEquals extends DatabaseQueryCondition {
}
// This item has an edge pointing to 'x' item
@annotation.JsonSerializable()
@JsonSerializable()
class DatabaseQueryConditionEdgeHasTarget extends DatabaseQueryCondition {
EdgeHasTarget value;
......@@ -744,7 +743,7 @@ class DatabaseQueryConditionEdgeHasTarget extends DatabaseQueryCondition {
_$DatabaseQueryConditionEdgeHasTargetToJson(this)..addAll({"type": runtimeType.toString()});
}
@annotation.JsonSerializable()
@JsonSerializable()
class DatabaseQueryConditionEdgeHasSource extends DatabaseQueryCondition {
EdgeHasSource value;
......@@ -757,7 +756,7 @@ class DatabaseQueryConditionEdgeHasSource extends DatabaseQueryCondition {
_$DatabaseQueryConditionEdgeHasSourceToJson(this)..addAll({"type": runtimeType.toString()});
}
@annotation.JsonSerializable()
@JsonSerializable()
class PropertyEquals {
String name;
dynamic value;
......@@ -769,7 +768,7 @@ class PropertyEquals {
Map<String, dynamic> toJson() => _$PropertyEqualsToJson(this);
}
@annotation.JsonSerializable()
@JsonSerializable()
class EdgeHasTarget {
String edgeName;
List<dynamic> target;
......@@ -781,7 +780,7 @@ class EdgeHasTarget {
Map<String, dynamic> toJson() => _$EdgeHasTargetToJson(this);
}
@annotation.JsonSerializable()
@JsonSerializable()
class EdgeHasSource {
String edgeName;
List<dynamic> source;
......
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'DatabaseQuery.dart';
part of 'database_query.dart';
// **************************************************************************
// JsonSerializableGenerator
......
export 'mobile_file_storage_controller.dart'
if (dart.library.html) 'web_file_storage_controller.dart';
import 'dart:io';
import 'package:crypto/crypto.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:memri/controllers/syncing/sync_controller.dart';
import 'package:moor/moor.dart';
import 'package:path_provider/path_provider.dart';
import 'package:crypto/crypto.dart';
import 'Syncing/SyncController.dart';
/// The FileStorageController class provides methods to store and retrieve files locally
class FileStorageController {
......
import 'package:crypto/crypto.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:idb_shim/idb.dart';
import 'package:idb_shim/idb_browser.dart';
import 'package:moor/moor.dart';
import 'package:crypto/crypto.dart';
import 'package:idb_shim/idb.dart';
/// The FileStorageController class provides methods to store and retrieve files locally
class FileStorageController {
......
import 'package:flutter/material.dart';
import 'package:memri/MemriApp/CVU/actions/CVUAction.dart';
import 'package:memri/MemriApp/CVU/definitions/CVUValue.dart';
import 'package:memri/MemriApp/CVU/definitions/CVUValue_Constant.dart';
import 'package:memri/MemriApp/CVU/resolving/CVUContext.dart';
import 'package:memri/MemriApp/CVU/resolving/CVUViewArguments.dart';
import 'package:memri/MemriApp/Controllers/Database/ItemRecord.dart';
import 'package:memri/MemriApp/Controllers/SceneController.dart';
import 'package:memri/MemriApp/UI/SceneContentView.dart';
import 'package:memri/MemriApp/UI/UIHelpers/NavigationHolder.dart';
import 'package:memri/MemriApp/UI/UIHelpers/utilities.dart';
import 'package:memri/MemriApp/UI/ViewContext.dart';
import 'package:memri/MemriApp/UI/ViewContextController.dart';
import 'AppController.dart';
import 'Database/NavigationStack.dart';
import 'package:memri/controllers/app_controller.dart';
import 'package:memri/controllers/scene_controller.dart';
import 'package:memri/controllers/view_context_controller.dart';
import 'package:memri/core/cvu/cvu_action.dart';
import 'package:memri/core/cvu/resolving/cvu_context.dart';
import 'package:memri/core/services/database/navigation_stack.dart';
import 'package:memri/models/cvu/cvu_value.dart';
import 'package:memri/models/cvu/cvu_value_constant.dart';
import 'package:memri/models/cvu/cvu_view_arguments.dart';
import 'package:memri/models/database/item_record.dart';
import 'package:memri/models/view_context.dart';
import 'package:memri/widgets/empty.dart';
import 'package:memri/widgets/navigation/navigation_holder.dart';
import 'package:memri/widgets/scene_content_view.dart';
class PageController extends ChangeNotifier {
AppController appController = AppController.shared;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment