workspace

This commit is contained in:
Ashita Prasad
2024-09-08 15:17:21 +05:30
parent bd5c83525e
commit 802d9e4607
14 changed files with 220 additions and 67 deletions

View File

@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_portal/flutter_portal.dart'; import 'package:flutter_portal/flutter_portal.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:window_manager/window_manager.dart' hide WindowCaption; import 'package:window_manager/window_manager.dart' hide WindowCaption;
import 'widgets/widgets.dart' show WindowCaption; import 'widgets/widgets.dart' show WindowCaption, WorkspaceSelector;
import 'providers/providers.dart'; import 'providers/providers.dart';
import 'extensions/extensions.dart'; import 'extensions/extensions.dart';
import 'screens/screens.dart'; import 'screens/screens.dart';

View File

@ -1,35 +1,62 @@
import 'package:apidash/providers/settings_providers.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'models/models.dart';
import 'providers/providers.dart';
import 'services/services.dart'; import 'services/services.dart';
import 'consts.dart' show kIsLinux, kIsMacOS, kIsWindows; import 'consts.dart';
import 'app.dart'; import 'app.dart';
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
final settingsModel = await getSettingsFromSharedPrefs();
await initApp(); await initApp(settingsModel: settingsModel);
await initWindow(); if (kIsDesktop) {
await initWindow(settingsModel: settingsModel);
}
runApp( runApp(
const ProviderScope( ProviderScope(
child: DashApp(), overrides: [
settingsProvider.overrideWith(
(ref) => ThemeStateNotifier(settingsModel: settingsModel),
)
],
child: const DashApp(),
), ),
); );
} }
Future<void> initApp() async { Future<void> initApp({SettingsModel? settingsModel}) async {
GoogleFonts.config.allowRuntimeFetching = false; GoogleFonts.config.allowRuntimeFetching = false;
await openBoxes(); await openBoxes(
await autoClearHistory(); kIsDesktop,
settingsModel?.workspaceFolderPath,
);
await autoClearHistory(settingsModel: settingsModel);
} }
Future<void> initWindow({Size? sz}) async { Future<void> initWindow({
Size? sz,
SettingsModel? settingsModel,
}) async {
if (kIsLinux) { if (kIsLinux) {
await setupInitialWindow(sz: sz); await setupInitialWindow(
sz: sz ?? settingsModel?.size,
);
} }
if (kIsMacOS || kIsWindows) { if (kIsMacOS || kIsWindows) {
var win = sz != null ? (sz, const Offset(100, 100)) : getInitialSize(); if (sz != null) {
await setupWindow(sz: win.$1, off: win.$2); await setupWindow(
sz: sz,
off: const Offset(100, 100),
);
} else {
await setupWindow(
sz: settingsModel?.size,
off: settingsModel?.offset,
);
}
} }
} }

View File

@ -14,6 +14,7 @@ class SettingsModel {
this.promptBeforeClosing = true, this.promptBeforeClosing = true,
this.activeEnvironmentId, this.activeEnvironmentId,
this.historyRetentionPeriod = HistoryRetentionPeriod.oneWeek, this.historyRetentionPeriod = HistoryRetentionPeriod.oneWeek,
this.workspaceFolderPath,
}); });
final bool isDark; final bool isDark;
@ -26,6 +27,7 @@ class SettingsModel {
final bool promptBeforeClosing; final bool promptBeforeClosing;
final String? activeEnvironmentId; final String? activeEnvironmentId;
final HistoryRetentionPeriod historyRetentionPeriod; final HistoryRetentionPeriod historyRetentionPeriod;
final String? workspaceFolderPath;
SettingsModel copyWith({ SettingsModel copyWith({
bool? isDark, bool? isDark,
@ -38,6 +40,7 @@ class SettingsModel {
bool? promptBeforeClosing, bool? promptBeforeClosing,
String? activeEnvironmentId, String? activeEnvironmentId,
HistoryRetentionPeriod? historyRetentionPeriod, HistoryRetentionPeriod? historyRetentionPeriod,
String? workspaceFolderPath,
}) { }) {
return SettingsModel( return SettingsModel(
isDark: isDark ?? this.isDark, isDark: isDark ?? this.isDark,
@ -52,6 +55,7 @@ class SettingsModel {
activeEnvironmentId: activeEnvironmentId ?? this.activeEnvironmentId, activeEnvironmentId: activeEnvironmentId ?? this.activeEnvironmentId,
historyRetentionPeriod: historyRetentionPeriod:
historyRetentionPeriod ?? this.historyRetentionPeriod, historyRetentionPeriod ?? this.historyRetentionPeriod,
workspaceFolderPath: workspaceFolderPath ?? this.workspaceFolderPath,
); );
} }
@ -86,8 +90,7 @@ class SettingsModel {
final promptBeforeClosing = data["promptBeforeClosing"] as bool?; final promptBeforeClosing = data["promptBeforeClosing"] as bool?;
final activeEnvironmentId = data["activeEnvironmentId"] as String?; final activeEnvironmentId = data["activeEnvironmentId"] as String?;
final historyRetentionPeriodStr = data["historyRetentionPeriod"] as String?; final historyRetentionPeriodStr = data["historyRetentionPeriod"] as String?;
HistoryRetentionPeriod historyRetentionPeriod = HistoryRetentionPeriod? historyRetentionPeriod;
HistoryRetentionPeriod.oneWeek;
if (historyRetentionPeriodStr != null) { if (historyRetentionPeriodStr != null) {
try { try {
historyRetentionPeriod = historyRetentionPeriod =
@ -96,6 +99,7 @@ class SettingsModel {
// pass // pass
} }
} }
final workspaceFolderPath = data["workspaceFolderPath"] as String?;
const sm = SettingsModel(); const sm = SettingsModel();
@ -109,7 +113,9 @@ class SettingsModel {
saveResponses: saveResponses, saveResponses: saveResponses,
promptBeforeClosing: promptBeforeClosing, promptBeforeClosing: promptBeforeClosing,
activeEnvironmentId: activeEnvironmentId, activeEnvironmentId: activeEnvironmentId,
historyRetentionPeriod: historyRetentionPeriod, historyRetentionPeriod:
historyRetentionPeriod ?? HistoryRetentionPeriod.oneWeek,
workspaceFolderPath: workspaceFolderPath,
); );
} }
@ -127,12 +133,13 @@ class SettingsModel {
"promptBeforeClosing": promptBeforeClosing, "promptBeforeClosing": promptBeforeClosing,
"activeEnvironmentId": activeEnvironmentId, "activeEnvironmentId": activeEnvironmentId,
"historyRetentionPeriod": historyRetentionPeriod.name, "historyRetentionPeriod": historyRetentionPeriod.name,
"workspaceFolderPath": workspaceFolderPath,
}; };
} }
@override @override
String toString() { String toString() {
return toJson().toString(); return kJsonEncoder.convert(toJson());
} }
@override @override
@ -149,7 +156,8 @@ class SettingsModel {
other.saveResponses == saveResponses && other.saveResponses == saveResponses &&
other.promptBeforeClosing == promptBeforeClosing && other.promptBeforeClosing == promptBeforeClosing &&
other.activeEnvironmentId == activeEnvironmentId && other.activeEnvironmentId == activeEnvironmentId &&
other.historyRetentionPeriod == historyRetentionPeriod; other.historyRetentionPeriod == historyRetentionPeriod &&
other.workspaceFolderPath == workspaceFolderPath;
} }
@override @override
@ -166,6 +174,7 @@ class SettingsModel {
promptBeforeClosing, promptBeforeClosing,
activeEnvironmentId, activeEnvironmentId,
historyRetentionPeriod, historyRetentionPeriod,
workspaceFolderPath,
); );
} }
} }

View File

@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../models/models.dart'; import '../models/models.dart';
import '../services/services.dart' show hiveHandler, HiveHandler; import '../services/services.dart';
import '../consts.dart'; import '../consts.dart';
final codegenLanguageStateProvider = StateProvider<CodegenLanguage>((ref) => final codegenLanguageStateProvider = StateProvider<CodegenLanguage>((ref) =>
@ -11,14 +11,13 @@ final activeEnvironmentIdStateProvider = StateProvider<String?>((ref) =>
ref.watch(settingsProvider.select((value) => value.activeEnvironmentId))); ref.watch(settingsProvider.select((value) => value.activeEnvironmentId)));
final StateNotifierProvider<ThemeStateNotifier, SettingsModel> final StateNotifierProvider<ThemeStateNotifier, SettingsModel>
settingsProvider = settingsProvider = StateNotifierProvider((ref) => ThemeStateNotifier());
StateNotifierProvider((ref) => ThemeStateNotifier(hiveHandler));
class ThemeStateNotifier extends StateNotifier<SettingsModel> { class ThemeStateNotifier extends StateNotifier<SettingsModel> {
ThemeStateNotifier(this.hiveHandler) : super(const SettingsModel()) { ThemeStateNotifier({this.settingsModel}) : super(const SettingsModel()) {
state = SettingsModel.fromJson(hiveHandler.settings); state = settingsModel ?? const SettingsModel();
} }
final HiveHandler hiveHandler; final SettingsModel? settingsModel;
Future<void> update({ Future<void> update({
bool? isDark, bool? isDark,
@ -31,6 +30,7 @@ class ThemeStateNotifier extends StateNotifier<SettingsModel> {
bool? promptBeforeClosing, bool? promptBeforeClosing,
String? activeEnvironmentId, String? activeEnvironmentId,
HistoryRetentionPeriod? historyRetentionPeriod, HistoryRetentionPeriod? historyRetentionPeriod,
String? workspaceFolderPath,
}) async { }) async {
state = state.copyWith( state = state.copyWith(
isDark: isDark, isDark: isDark,
@ -43,7 +43,8 @@ class ThemeStateNotifier extends StateNotifier<SettingsModel> {
promptBeforeClosing: promptBeforeClosing, promptBeforeClosing: promptBeforeClosing,
activeEnvironmentId: activeEnvironmentId, activeEnvironmentId: activeEnvironmentId,
historyRetentionPeriod: historyRetentionPeriod, historyRetentionPeriod: historyRetentionPeriod,
workspaceFolderPath: workspaceFolderPath,
); );
await hiveHandler.saveSettings(state.toJson()); await setSettingsToSharedPrefs(state);
} }
} }

View File

@ -1,18 +1,9 @@
import 'package:apidash/models/models.dart'; import 'package:apidash/models/models.dart';
import 'package:apidash/utils/utils.dart'; import 'package:apidash/utils/utils.dart';
import 'package:apidash/consts.dart';
import 'hive_services.dart'; import 'hive_services.dart';
Future<void> autoClearHistory() async { Future<void> autoClearHistory({SettingsModel? settingsModel}) async {
final settingsMap = hiveHandler.settings; final historyRetentionPeriod = settingsModel?.historyRetentionPeriod;
final retentionPeriod = settingsMap['historyRetentionPeriod'];
HistoryRetentionPeriod historyRetentionPeriod =
HistoryRetentionPeriod.oneWeek;
if (retentionPeriod != null) {
historyRetentionPeriod =
HistoryRetentionPeriod.values.byName(retentionPeriod);
}
DateTime? retentionDate = getRetentionDate(historyRetentionPeriod); DateTime? retentionDate = getRetentionDate(historyRetentionPeriod);
if (retentionDate == null) { if (retentionDate == null) {

View File

@ -1,4 +1,3 @@
import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart'; import 'package:hive_flutter/hive_flutter.dart';
const String kDataBox = "apidash-data"; const String kDataBox = "apidash-data";
@ -11,54 +10,36 @@ const String kHistoryMetaBox = "apidash-history-meta";
const String kHistoryBoxIds = "historyIds"; const String kHistoryBoxIds = "historyIds";
const String kHistoryLazyBox = "apidash-history-lazy"; const String kHistoryLazyBox = "apidash-history-lazy";
const String kSettingsBox = "apidash-settings"; Future<void> openBoxes(
bool isDesktop,
Future<void> openBoxes() async { String? workspaceFolderPath,
await Hive.initFlutter(); ) async {
if (isDesktop) {
Hive.init(workspaceFolderPath);
} else {
await Hive.initFlutter();
}
await Hive.openBox(kDataBox); await Hive.openBox(kDataBox);
await Hive.openBox(kSettingsBox);
await Hive.openBox(kEnvironmentBox); await Hive.openBox(kEnvironmentBox);
await Hive.openBox(kHistoryMetaBox); await Hive.openBox(kHistoryMetaBox);
await Hive.openLazyBox(kHistoryLazyBox); await Hive.openLazyBox(kHistoryLazyBox);
} }
(Size?, Offset?) getInitialSize() {
Size? sz;
Offset? off;
var settingsBox = Hive.box(kSettingsBox);
double? w = settingsBox.get("width") as double?;
double? h = settingsBox.get("height") as double?;
if (w != null && h != null) {
sz = Size(w, h);
}
double? dx = settingsBox.get("dx") as double?;
double? dy = settingsBox.get("dy") as double?;
if (dx != null && dy != null) {
off = Offset(dx, dy);
}
return (sz, off);
}
final hiveHandler = HiveHandler(); final hiveHandler = HiveHandler();
class HiveHandler { class HiveHandler {
late final Box dataBox; late final Box dataBox;
late final Box settingsBox;
late final Box environmentBox; late final Box environmentBox;
late final Box historyMetaBox; late final Box historyMetaBox;
late final LazyBox historyLazyBox; late final LazyBox historyLazyBox;
HiveHandler() { HiveHandler() {
dataBox = Hive.box(kDataBox); dataBox = Hive.box(kDataBox);
settingsBox = Hive.box(kSettingsBox);
environmentBox = Hive.box(kEnvironmentBox); environmentBox = Hive.box(kEnvironmentBox);
historyMetaBox = Hive.box(kHistoryMetaBox); historyMetaBox = Hive.box(kHistoryMetaBox);
historyLazyBox = Hive.lazyBox(kHistoryLazyBox); historyLazyBox = Hive.lazyBox(kHistoryLazyBox);
} }
Map get settings => settingsBox.toMap();
Future<void> saveSettings(Map data) => settingsBox.putAll(data);
dynamic getIds() => dataBox.get(kKeyDataBoxIds); dynamic getIds() => dataBox.get(kKeyDataBoxIds);
Future<void> setIds(List<String>? ids) => dataBox.put(kKeyDataBoxIds, ids); Future<void> setIds(List<String>? ids) => dataBox.put(kKeyDataBoxIds, ids);

View File

@ -2,3 +2,4 @@ export 'http_service.dart';
export 'hive_services.dart'; export 'hive_services.dart';
export 'history_service.dart'; export 'history_service.dart';
export 'window_services.dart'; export 'window_services.dart';
export 'shared_preferences_services.dart';

View File

@ -0,0 +1,23 @@
import 'package:apidash/consts.dart';
import 'package:apidash/models/models.dart';
import 'package:shared_preferences/shared_preferences.dart';
const String kSharedPrefSettingsKey = 'apidash-settings';
Future<SettingsModel?> getSettingsFromSharedPrefs() async {
final prefs = await SharedPreferences.getInstance();
var settingsStr = prefs.getString(kSharedPrefSettingsKey);
if (settingsStr != null) {
var jsonSettings = kJsonDecoder.convert(settingsStr);
var jsonMap = Map<String, Object?>.from(jsonSettings);
var settingsModel = SettingsModel.fromJson(jsonMap);
return settingsModel;
} else {
return null;
}
}
Future<void> setSettingsToSharedPrefs(SettingsModel settingsModel) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(kSharedPrefSettingsKey, settingsModel.toString());
}

View File

@ -114,7 +114,7 @@ List<HistoryMetaModel> getRequestGroup(
return requestGroup; return requestGroup;
} }
DateTime? getRetentionDate(HistoryRetentionPeriod retentionPeriod) { DateTime? getRetentionDate(HistoryRetentionPeriod? retentionPeriod) {
DateTime now = DateTime.now(); DateTime now = DateTime.now();
DateTime today = stripTime(now); DateTime today = stripTime(now);

View File

@ -60,3 +60,4 @@ export 'tabs.dart';
export 'texts.dart'; export 'texts.dart';
export 'uint8_audio_player.dart'; export 'uint8_audio_player.dart';
export 'window_caption.dart'; export 'window_caption.dart';
export 'workspace_selector.dart';

View File

@ -0,0 +1,62 @@
import 'package:file_selector/file_selector.dart';
import 'package:apidash/services/hive_services.dart';
import 'package:flutter/material.dart';
class WorkspaceSelector extends StatefulWidget {
final Future<void> Function(String)? onSelect;
const WorkspaceSelector({
super.key,
required this.onSelect,
});
@override
WorkspaceSelectorState createState() => WorkspaceSelectorState();
}
class WorkspaceSelectorState extends State<WorkspaceSelector> {
void selectFolder() async {
String? selectedDirectory = await getDirectoryPath();
if (selectedDirectory != null) {
widget.onSelect?.call(selectedDirectory);
}
}
@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: openHiveBoxes(snapshot.data!),
builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
// if loading show circularLoader
if (snapshot.connectionState != ConnectionState.done) {
return circularLoader;
}
// Display widget
return widget.child;
},
);
},
);
}
}

View File

@ -1215,6 +1215,62 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.8" version: "0.3.8"
shared_preferences:
dependency: "direct main"
description:
name: shared_preferences
sha256: "746e5369a43170c25816cc472ee016d3a66bc13fcf430c0bc41ad7b4b2922051"
url: "https://pub.dev"
source: hosted
version: "2.3.2"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
sha256: "480ba4345773f56acda9abf5f50bd966f581dac5d514e5fc4a18c62976bbba7e"
url: "https://pub.dev"
source: hosted
version: "2.3.2"
shared_preferences_foundation:
dependency: transitive
description:
name: shared_preferences_foundation
sha256: c4b35f6cb8f63c147312c054ce7c2254c8066745125264f0c88739c417fc9d9f
url: "https://pub.dev"
source: hosted
version: "2.5.2"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
shared_preferences_platform_interface:
dependency: transitive
description:
name: shared_preferences_platform_interface
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
shared_preferences_web:
dependency: transitive
description:
name: shared_preferences_web
sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e
url: "https://pub.dev"
source: hosted
version: "2.4.2"
shared_preferences_windows:
dependency: transitive
description:
name: shared_preferences_windows
sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
shelf: shelf:
dependency: transitive dependency: transitive
description: description:

View File

@ -63,6 +63,7 @@ dependencies:
provider: ^6.1.2 provider: ^6.1.2
riverpod: ^2.5.1 riverpod: ^2.5.1
scrollable_positioned_list: ^0.3.8 scrollable_positioned_list: ^0.3.8
shared_preferences: ^2.3.2
url_launcher: ^6.2.5 url_launcher: ^6.2.5
uuid: ^4.3.3 uuid: ^4.3.3
vector_graphics_compiler: ^1.1.9+1 vector_graphics_compiler: ^1.1.9+1

View File

@ -39,7 +39,7 @@ void main() {
} }
return null; return null;
}); });
await openBoxes(); await openBoxes(false, null);
final flamante = rootBundle.load('google_fonts/OpenSans-Medium.ttf'); final flamante = rootBundle.load('google_fonts/OpenSans-Medium.ttf');
final fontLoader = FontLoader('OpenSans')..addFont(flamante); final fontLoader = FontLoader('OpenSans')..addFont(flamante);
await fontLoader.load(); await fontLoader.load();