Skip to content

Commit

Permalink
Merge pull request foss42#464 from foss42/dev-workspace
Browse files Browse the repository at this point in the history
Users can select the persistent data location
  • Loading branch information
ashitaprasad authored Sep 9, 2024
2 parents bd5c835 + 8820d26 commit 5b7fb9d
Show file tree
Hide file tree
Showing 19 changed files with 478 additions and 91 deletions.
19 changes: 15 additions & 4 deletions integration_test/test_helper.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import 'package:apidash/models/settings_model.dart';
import 'package:apidash/providers/providers.dart';
import 'package:apidash/services/services.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
Expand Down Expand Up @@ -34,17 +37,24 @@ class ApidashTestHelper {
final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;

await app.initApp();
await app.initApp(false);
await app.initWindow(sz: size);

return binding;
}

static Future<void> loadApp(WidgetTester tester) async {
await app.initApp();
await app.initApp(false);
await tester.pumpWidget(
const ProviderScope(
child: DashApp(),
ProviderScope(
overrides: [
settingsProvider.overrideWith(
(ref) => ThemeStateNotifier(
settingsModel: const SettingsModel()
.copyWithPath(workspaceFolderPath: "test")),
)
],
child: const DashApp(),
),
);
}
Expand Down Expand Up @@ -123,6 +133,7 @@ void apidashWidgetTest(
size: width != null ? Size(width, kMinWindowSize.height) : null);
await ApidashTestHelper.loadApp(widgetTester);
await test(widgetTester, ApidashTestHelper(widgetTester));
await clearSharedPrefs();
},
semanticsEnabled: false,
);
Expand Down
55 changes: 38 additions & 17 deletions lib/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import 'package:flutter/material.dart';
import 'package:flutter_portal/flutter_portal.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
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 'services/services.dart';
import 'extensions/extensions.dart';
import 'screens/screens.dart';
import 'consts.dart';
Expand Down Expand Up @@ -107,29 +108,49 @@ class DashApp extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final isDarkMode =
ref.watch(settingsProvider.select((value) => value.isDark));
final workspaceFolderPath = ref
.watch(settingsProvider.select((value) => value.workspaceFolderPath));
final showWorkspaceSelector = kIsDesktop && (workspaceFolderPath == null);
return Portal(
child: MaterialApp(
debugShowCheckedModeBanner: false,
theme: kLightMaterialAppTheme,
darkTheme: kDarkMaterialAppTheme,
themeMode: isDarkMode ? ThemeMode.dark : ThemeMode.light,
home: Stack(
children: [
!kIsLinux && !kIsMobile
? const App()
: context.isMediumWindow
? const MobileDashboard()
: const Dashboard(),
if (kIsWindows)
SizedBox(
height: 29,
child: WindowCaption(
backgroundColor: Colors.transparent,
brightness: isDarkMode ? Brightness.dark : Brightness.light,
),
home: showWorkspaceSelector
? WorkspaceSelector(
onContinue: (val) async {
await openBoxes(kIsDesktop, val);
ref
.read(settingsProvider.notifier)
.update(workspaceFolderPath: val);
},
onCancel: () async {
try {
await windowManager.destroy();
} catch (e) {
debugPrint(e.toString());
}
},
)
: Stack(
children: [
!kIsLinux && !kIsMobile
? const App()
: context.isMediumWindow
? const MobileDashboard()
: const Dashboard(),
if (kIsWindows)
SizedBox(
height: 29,
child: WindowCaption(
backgroundColor: Colors.transparent,
brightness:
isDarkMode ? Brightness.dark : Brightness.light,
),
),
],
),
],
),
),
);
}
Expand Down
5 changes: 5 additions & 0 deletions lib/consts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,9 @@ const kLabelSaving = "Saving";
const kLabelSaved = "Saved";
const kLabelCode = "Code";
const kLabelDuplicate = "Duplicate";
const kLabelSelect = "Select";
const kLabelContinue = "Continue";
const kLabelCancel = "Cancel";
// Request Pane
const kLabelRequest = "Request";
const kLabelHideCode = "Hide Code";
Expand Down Expand Up @@ -778,3 +781,5 @@ const kNullResponseModelError = "Error: Response data does not exist.";
const kMsgNullBody = "Response body is missing (null).";
const kMsgNoContent = "No content";
const kMsgUnknowContentType = "Unknown Response Content-Type";
// Workspace Selector
const kMsgSelectWorkspace = "Create your workspace";
73 changes: 60 additions & 13 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,35 +1,82 @@
import 'package:apidash/providers/settings_providers.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart';
import 'models/models.dart';
import 'providers/providers.dart';
import 'services/services.dart';
import 'consts.dart' show kIsLinux, kIsMacOS, kIsWindows;
import 'consts.dart';
import 'app.dart';

void main() async {
WidgetsFlutterBinding.ensureInitialized();

await initApp();
await initWindow();
var settingsModel = await getSettingsFromSharedPrefs();
final initStatus = await initApp(
kIsDesktop,
settingsModel: settingsModel,
);
if (kIsDesktop) {
await initWindow(settingsModel: settingsModel);
}
if (!initStatus) {
settingsModel = settingsModel?.copyWithPath(workspaceFolderPath: null);
}

runApp(
const ProviderScope(
child: DashApp(),
ProviderScope(
overrides: [
settingsProvider.overrideWith(
(ref) => ThemeStateNotifier(settingsModel: settingsModel),
)
],
child: const DashApp(),
),
);
}

Future<void> initApp() async {
Future<bool> initApp(
bool initializeUsingPath, {
SettingsModel? settingsModel,
}) async {
GoogleFonts.config.allowRuntimeFetching = false;
await openBoxes();
await autoClearHistory();
try {
debugPrint("initializeUsingPath: $initializeUsingPath");
debugPrint("workspaceFolderPath: ${settingsModel?.workspaceFolderPath}");
final openBoxesStatus = await openBoxes(
initializeUsingPath,
settingsModel?.workspaceFolderPath,
);
debugPrint("openBoxesStatus: $openBoxesStatus");
if (openBoxesStatus) {
await autoClearHistory(settingsModel: settingsModel);
}
return openBoxesStatus;
} catch (e) {
debugPrint("initApp failed due to $e");
return false;
}
}

Future<void> initWindow({Size? sz}) async {
Future<void> initWindow({
Size? sz,
SettingsModel? settingsModel,
}) async {
if (kIsLinux) {
await setupInitialWindow(sz: sz);
await setupInitialWindow(
sz: sz ?? settingsModel?.size,
);
}
if (kIsMacOS || kIsWindows) {
var win = sz != null ? (sz, const Offset(100, 100)) : getInitialSize();
await setupWindow(sz: win.$1, off: win.$2);
if (sz != null) {
await setupWindow(
sz: sz,
off: const Offset(100, 100),
);
} else {
await setupWindow(
sz: settingsModel?.size,
off: settingsModel?.offset,
);
}
}
}
37 changes: 32 additions & 5 deletions lib/models/settings_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class SettingsModel {
this.promptBeforeClosing = true,
this.activeEnvironmentId,
this.historyRetentionPeriod = HistoryRetentionPeriod.oneWeek,
this.workspaceFolderPath,
});

final bool isDark;
Expand All @@ -26,6 +27,7 @@ class SettingsModel {
final bool promptBeforeClosing;
final String? activeEnvironmentId;
final HistoryRetentionPeriod historyRetentionPeriod;
final String? workspaceFolderPath;

SettingsModel copyWith({
bool? isDark,
Expand All @@ -38,6 +40,7 @@ class SettingsModel {
bool? promptBeforeClosing,
String? activeEnvironmentId,
HistoryRetentionPeriod? historyRetentionPeriod,
String? workspaceFolderPath,
}) {
return SettingsModel(
isDark: isDark ?? this.isDark,
Expand All @@ -52,6 +55,25 @@ class SettingsModel {
activeEnvironmentId: activeEnvironmentId ?? this.activeEnvironmentId,
historyRetentionPeriod:
historyRetentionPeriod ?? this.historyRetentionPeriod,
workspaceFolderPath: workspaceFolderPath ?? this.workspaceFolderPath,
);
}

SettingsModel copyWithPath({
String? workspaceFolderPath,
}) {
return SettingsModel(
isDark: isDark,
alwaysShowCollectionPaneScrollbar: alwaysShowCollectionPaneScrollbar,
size: size,
defaultUriScheme: defaultUriScheme,
defaultCodeGenLang: defaultCodeGenLang,
offset: offset,
saveResponses: saveResponses,
promptBeforeClosing: promptBeforeClosing,
activeEnvironmentId: activeEnvironmentId,
historyRetentionPeriod: historyRetentionPeriod,
workspaceFolderPath: workspaceFolderPath,
);
}

Expand Down Expand Up @@ -86,8 +108,7 @@ class SettingsModel {
final promptBeforeClosing = data["promptBeforeClosing"] as bool?;
final activeEnvironmentId = data["activeEnvironmentId"] as String?;
final historyRetentionPeriodStr = data["historyRetentionPeriod"] as String?;
HistoryRetentionPeriod historyRetentionPeriod =
HistoryRetentionPeriod.oneWeek;
HistoryRetentionPeriod? historyRetentionPeriod;
if (historyRetentionPeriodStr != null) {
try {
historyRetentionPeriod =
Expand All @@ -96,6 +117,7 @@ class SettingsModel {
// pass
}
}
final workspaceFolderPath = data["workspaceFolderPath"] as String?;

const sm = SettingsModel();

Expand All @@ -109,7 +131,9 @@ class SettingsModel {
saveResponses: saveResponses,
promptBeforeClosing: promptBeforeClosing,
activeEnvironmentId: activeEnvironmentId,
historyRetentionPeriod: historyRetentionPeriod,
historyRetentionPeriod:
historyRetentionPeriod ?? HistoryRetentionPeriod.oneWeek,
workspaceFolderPath: workspaceFolderPath,
);
}

Expand All @@ -127,12 +151,13 @@ class SettingsModel {
"promptBeforeClosing": promptBeforeClosing,
"activeEnvironmentId": activeEnvironmentId,
"historyRetentionPeriod": historyRetentionPeriod.name,
"workspaceFolderPath": workspaceFolderPath,
};
}

@override
String toString() {
return toJson().toString();
return kJsonEncoder.convert(toJson());
}

@override
Expand All @@ -149,7 +174,8 @@ class SettingsModel {
other.saveResponses == saveResponses &&
other.promptBeforeClosing == promptBeforeClosing &&
other.activeEnvironmentId == activeEnvironmentId &&
other.historyRetentionPeriod == historyRetentionPeriod;
other.historyRetentionPeriod == historyRetentionPeriod &&
other.workspaceFolderPath == workspaceFolderPath;
}

@override
Expand All @@ -166,6 +192,7 @@ class SettingsModel {
promptBeforeClosing,
activeEnvironmentId,
historyRetentionPeriod,
workspaceFolderPath,
);
}
}
15 changes: 8 additions & 7 deletions lib/providers/settings_providers.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../models/models.dart';
import '../services/services.dart' show hiveHandler, HiveHandler;
import '../services/services.dart';
import '../consts.dart';

final codegenLanguageStateProvider = StateProvider<CodegenLanguage>((ref) =>
Expand All @@ -11,14 +11,13 @@ final activeEnvironmentIdStateProvider = StateProvider<String?>((ref) =>
ref.watch(settingsProvider.select((value) => value.activeEnvironmentId)));

final StateNotifierProvider<ThemeStateNotifier, SettingsModel>
settingsProvider =
StateNotifierProvider((ref) => ThemeStateNotifier(hiveHandler));
settingsProvider = StateNotifierProvider((ref) => ThemeStateNotifier());

class ThemeStateNotifier extends StateNotifier<SettingsModel> {
ThemeStateNotifier(this.hiveHandler) : super(const SettingsModel()) {
state = SettingsModel.fromJson(hiveHandler.settings);
ThemeStateNotifier({this.settingsModel}) : super(const SettingsModel()) {
state = settingsModel ?? const SettingsModel();
}
final HiveHandler hiveHandler;
final SettingsModel? settingsModel;

Future<void> update({
bool? isDark,
Expand All @@ -31,6 +30,7 @@ class ThemeStateNotifier extends StateNotifier<SettingsModel> {
bool? promptBeforeClosing,
String? activeEnvironmentId,
HistoryRetentionPeriod? historyRetentionPeriod,
String? workspaceFolderPath,
}) async {
state = state.copyWith(
isDark: isDark,
Expand All @@ -43,7 +43,8 @@ class ThemeStateNotifier extends StateNotifier<SettingsModel> {
promptBeforeClosing: promptBeforeClosing,
activeEnvironmentId: activeEnvironmentId,
historyRetentionPeriod: historyRetentionPeriod,
workspaceFolderPath: workspaceFolderPath,
);
await hiveHandler.saveSettings(state.toJson());
await setSettingsToSharedPrefs(state);
}
}
Loading

0 comments on commit 5b7fb9d

Please sign in to comment.