-
Notifications
You must be signed in to change notification settings - Fork 348
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
Resolve issue 359 #413
Resolve issue 359 #413
Changes from all commits
2781ab4
8632ef1
ff1ad1f
3b08a27
a417d2d
1dc2e40
5164dce
3be3f74
b457622
a29c473
f8d56d5
597414b
21c5009
f1ddf7a
172de14
0493f7b
f56c322
c64fbf0
c82763d
1b719d7
a0fcb2a
ed2b222
7f92210
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import 'package:flutter/foundation.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:hive_flutter/hive_flutter.dart'; | ||
import 'package:path/path.dart'; | ||
|
||
/// Flutter extensions for Hive. | ||
extension HiveWithFolder on HiveInterface { | ||
/// Initializes Hive with the path from [appDir]. | ||
/// | ||
/// You can provide a [subDir] where the boxes should be stored. | ||
Future<void> initHiveWithRootFolder(String appDir, [String? subDir]) async { | ||
WidgetsFlutterBinding.ensureInitialized(); | ||
if (kIsWeb) return; | ||
|
||
init(join(appDir, subDir)); | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the purpose of this extension. This task can be done by a hive utility function. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// Store hive save folder path. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These are not models. They are shared_preferences utility functions. |
||
// SharedPreferences dynamicall changes saving folder based on platform, which isn't null. | ||
// Contrary to this hive stores the data in `getApplicationDocumentsDirectory()` given by | ||
// the path_provider package. Which is platform dependent and could be null. | ||
// See this issue for more details: | ||
// - https://github.com/foss42/apidash/issues/359 | ||
|
||
import 'package:shared_preferences/shared_preferences.dart'; | ||
|
||
// The key to store the folder path in shared preferences. | ||
const String kHiveSaveFolder = 'hive_save_folder'; | ||
|
||
Future<String?> getHiveSaveFolder() async { | ||
// Retrieves the folder path where hive stores data. | ||
// Which is stored in shared preferences. | ||
|
||
// Getting the shared preferences instance. | ||
final prefs = await SharedPreferences.getInstance(); | ||
// Getting the folder path. | ||
return prefs.getString(kHiveSaveFolder); | ||
} | ||
|
||
Future<void> setHiveSaveFolder(String folder) async { | ||
// Sets the folder path where hive stores data. | ||
|
||
// Getting the shared preferences instance. | ||
final prefs = await SharedPreferences.getInstance(); | ||
// Setting the folder path. | ||
await prefs.setString(kHiveSaveFolder, folder); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
import 'package:apidash/extensions/load_hive_extension.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:hive_flutter/hive_flutter.dart'; | ||
|
||
|
@@ -8,8 +9,8 @@ const String kKeyEnvironmentBoxIds = "environmentIds"; | |
|
||
const String kSettingsBox = "apidash-settings"; | ||
|
||
Future<void> openBoxes() async { | ||
await Hive.initFlutter(); | ||
Future<void> openBoxes(String hiveSaveFolder) async { | ||
await Hive.initHiveWithRootFolder(hiveSaveFolder); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will get changed according to the comment above |
||
await Hive.openBox(kDataBox); | ||
await Hive.openBox(kSettingsBox); | ||
await Hive.openBox(kEnvironmentBox); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import 'package:apidash/models/hive_storage_folder.dart'; | ||
import 'package:apidash/services/hive_services.dart'; | ||
import 'package:flutter/material.dart'; | ||
|
||
class HiveDirectorySelector extends StatefulWidget { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does it require a Stateful Widget or Stateless can work? |
||
final Widget child; | ||
final Future<String?> Function() getDirectoryPath; | ||
const HiveDirectorySelector({super.key, required this.child, required this.getDirectoryPath}); | ||
|
||
@override | ||
HiveDirectorySelectorState createState() => HiveDirectorySelectorState(); | ||
} | ||
|
||
class HiveDirectorySelectorState extends State<HiveDirectorySelector> { | ||
void selectFolder() async { | ||
// Show the folder selection menu | ||
String? selectedDirectory = await widget.getDirectoryPath(); | ||
// TODO: check if can write in current folder | ||
// If the selected selectedDirectory isn't null save it as hive save folder | ||
if (selectedDirectory != null) setHiveSaveFolder(selectedDirectory); | ||
// Changing the state of application | ||
setState(() {}); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
const circularLoader = MaterialApp( | ||
home: Scaffold( | ||
body: Center( | ||
child: CircularProgressIndicator(), | ||
), | ||
), | ||
); | ||
|
||
return FutureBuilder<String?>( | ||
future: getHiveSaveFolder(), | ||
builder: (BuildContext context, AsyncSnapshot<String?> snapshot) { | ||
if (snapshot.connectionState != ConnectionState.done) { | ||
return circularLoader; | ||
} | ||
|
||
// If there isn't hive selected folder choose it | ||
if (snapshot.data == null) { | ||
selectFolder(); | ||
return circularLoader; | ||
} | ||
|
||
// Once _hiveSaveFolder is set, display DashApp after hive init | ||
return FutureBuilder<void>( | ||
future: openBoxes(snapshot.data!), | ||
builder: (BuildContext context, AsyncSnapshot<void> snapshot) { | ||
// if loading show circularLoader | ||
if (snapshot.connectionState != ConnectionState.done) { | ||
return circularLoader; | ||
} | ||
// Display widget | ||
return widget.child; | ||
}, | ||
); | ||
}, | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import 'dart:io'; | ||
|
||
import 'package:apidash/models/hive_storage_folder.dart'; | ||
import 'package:shared_preferences/shared_preferences.dart'; | ||
import 'package:test/test.dart'; | ||
|
||
void main() async{ | ||
Directory tempDir = | ||
await Directory.systemTemp.createTemp('save_folder_path'); | ||
|
||
test('Load Hive directory', () async { | ||
SharedPreferences.setMockInitialValues({kHiveSaveFolder: tempDir.path}); | ||
expect(await getHiveSaveFolder(), tempDir.path); | ||
}); | ||
|
||
test('Saving Hive directory', () async { | ||
await setHiveSaveFolder(tempDir.path); | ||
expect(await getHiveSaveFolder(), tempDir.path); | ||
}); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import 'dart:io'; | ||
|
||
import 'package:apidash/widgets/hive_directory_selector.dart'; | ||
import 'package:apidash/models/hive_storage_folder.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_test/flutter_test.dart'; | ||
import 'package:shared_preferences/shared_preferences.dart'; | ||
|
||
void main() async { | ||
Directory tempDir = await Directory.systemTemp.createTemp('hive_dir_temp'); | ||
|
||
testWidgets('Given valid path, Then load the child component', (widgetTester) async { | ||
await widgetTester.runAsync(() async { | ||
// Set the hive save folder | ||
SharedPreferences.setMockInitialValues({}); | ||
await setHiveSaveFolder(tempDir.path); | ||
|
||
// Rendering the widgets | ||
await widgetTester.pumpWidget( | ||
HiveDirectorySelector( | ||
getDirectoryPath: () async => tempDir.path, | ||
child: Container(), | ||
), | ||
); | ||
|
||
// Find the container widget in the tree | ||
expect(find.byType(Container), findsOneWidget); | ||
}); | ||
}); | ||
|
||
testWidgets('Given when no path is set, Then set hive save folder', | ||
(widgetTester) async { | ||
await widgetTester.runAsync(() async { | ||
// Checking inital hive save folder to be null | ||
SharedPreferences.setMockInitialValues({}); | ||
expect(await getHiveSaveFolder(), null); | ||
|
||
// rendering the widgets | ||
await widgetTester.pumpWidget( | ||
HiveDirectorySelector( | ||
getDirectoryPath: () async => tempDir.path, | ||
child: Container(), | ||
), | ||
); | ||
|
||
// making a pump to render the widgets | ||
await widgetTester.pump(); | ||
|
||
// check if CircularProgressIndicator is shown | ||
expect(find.byType(CircularProgressIndicator), findsOneWidget); | ||
|
||
// check if the function `selectFolder` is called | ||
final state = widgetTester.state(find.byType(HiveDirectorySelector)) | ||
as HiveDirectorySelectorState; | ||
expect(state.selectFolder, isNotNull, | ||
reason: "The function selectFolder isn't rechable."); | ||
|
||
// check if the hive save folder is set | ||
expect(await getHiveSaveFolder(), tempDir.path); | ||
}); | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WidgetsFlutterBinding.ensureInitialized(); should not be hidden in this function. It should be in
main()
as it is currently.