Skip to content

Commit

Permalink
feat: server config modifier dialog (indev)
Browse files Browse the repository at this point in the history
  • Loading branch information
FriesI23 committed Jan 21, 2025
1 parent 4f6a2fd commit 390b18c
Show file tree
Hide file tree
Showing 11 changed files with 527 additions and 2 deletions.
1 change: 1 addition & 0 deletions lib/common/consts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const int appCalendarBarMaxOccupyPrt = 70;
const int appCalendarBarMinOccupyPrt = 20;
const int appCalendarBarDefualtOccupyPrt = 50;
const int kHabitLargeScreenAdaptWidth = 600;
const int kHabitLargeScreenAdaptHeight = 400;
//#endregion

//#region l10n
Expand Down
49 changes: 49 additions & 0 deletions lib/model/app_sync_server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import 'package:copy_with_extension/copy_with_extension.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:uuid/uuid.dart';

import '../common/enums.dart';
import 'common.dart';
Expand Down Expand Up @@ -75,6 +76,16 @@ abstract interface class AppSyncServer implements JsonAdaptor {
}
}

static AppSyncServer? newServer(AppSyncServerType type) {
final identity = const Uuid().v4();
switch (type) {
case AppSyncServerType.webdav:
return AppWebDavSyncServer.newServer(identity: identity, path: '');
default:
return null;
}
}

String get name;
String get identity;
DateTime get createTime;
Expand All @@ -87,6 +98,7 @@ abstract interface class AppSyncServer implements JsonAdaptor {
bool get verified;
bool get configed;

AppSyncServerForm toForm();
String toDebugString();
}

Expand Down Expand Up @@ -196,6 +208,11 @@ final class AppWebDavSyncServer implements AppSyncServer {
factory AppWebDavSyncServer.fromJson(Map<String, dynamic> json) =>
_$AppWebDavSyncServerFromJson(json);

factory AppWebDavSyncServer.fromForm(AppSyncServerForm form) {
//TODO: implement fromForm
throw UnimplementedError();
}

@override
Iterable<AppSyncServerMobileNetwork> get syncMobileNetworks =>
_syncMobileNetworks;
Expand All @@ -207,6 +224,15 @@ final class AppWebDavSyncServer implements AppSyncServer {
@override
Map<String, dynamic> toJson() => _$AppWebDavSyncServerToJson(this);

@override
AppSyncServerForm toForm() => AppSyncServerForm(
uuid: UuidValue.fromString(identity),
createTime: createTime,
modifyTime: modifyTime,
type: type,
path: path.toString(),
);

@override
String toDebugString() {
return """AppWebDavSyncServer(
Expand All @@ -227,3 +253,26 @@ final class AppWebDavSyncServer implements AppSyncServer {
)""";
}
}

class AppSyncServerForm {
final UuidValue uuid;
final DateTime createTime;
final DateTime modifyTime;

AppSyncServerType type;

String? path;

AppSyncServerForm({
required this.uuid,
required this.type,
required this.createTime,
required this.modifyTime,
this.path,
});

@override
String toString() => 'AppSyncServerForm(uuid=$uuid,type=$type,'
'createTime=$createTime,modifyTime=$modifyTime,'
'path=$path)';
}
69 changes: 69 additions & 0 deletions lib/provider/app_sync_server_form.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright 2025 Fries_I23
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import 'package:flutter/material.dart';
import 'package:uuid/uuid.dart';

import '../logging/helper.dart';
import '../model/app_sync_server.dart';
import 'commons.dart';

class AppSyncServerFormViewModel extends ChangeNotifier
implements ProviderMounted {
final AppSyncServer? initServerConfig;

bool _mounted = true;
AppSyncServer? _crtServerConfig;

late AppSyncServerForm _form;

AppSyncServerFormViewModel({
this.initServerConfig,
}) {
_form = initServerConfig?.toForm() ?? getDefaultForm();
}

@override
void dispose() {
if (!_mounted) return;
super.dispose();
_mounted = false;
}

@override
bool get mounted => _mounted;

AppSyncServerForm getDefaultForm() =>
AppWebDavSyncServer.newServer(identity: const Uuid().v4(), path: '')
.toForm();

AppSyncServer? get crtServerConfig => initServerConfig ?? _crtServerConfig;

void updateCrtServerConfig(AppSyncServer? newConfig) {
if (newConfig != crtServerConfig) {
appLog.load.info("$runtimeType.updateCrtServerConfig", ex: [newConfig]);
_crtServerConfig = newConfig;
notifyListeners();
}
}

AppSyncServerType get type => _form.type;
set type(AppSyncServerType value) {
if (type == value) return;
_form = value != crtServerConfig?.type
? AppSyncServer.newServer(value)?.toForm() ?? getDefaultForm()
: crtServerConfig!.toForm();
notifyListeners();
}
}
82 changes: 82 additions & 0 deletions lib/view/common/app_ui_layout_builder.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright 2025 Fries_I23
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import 'package:flutter/material.dart';

import '../../common/consts.dart';

enum UiLayoutType {
/// Small
s(0),

/// Large
l(10);

final int value;

const UiLayoutType(this.value);
}

class AppUiLayoutBuilder extends StatelessWidget {
final Widget? child;
final bool ignoreWidth;
final bool ignoreHeight;
final UiLayoutType defaultUiType;
final Widget Function(
BuildContext context,
UiLayoutType layoutType,
Widget? child,
) builder;

const AppUiLayoutBuilder({
super.key,
this.ignoreHeight = true,
this.ignoreWidth = false,
this.defaultUiType = UiLayoutType.s,
this.child,
required this.builder,
});

@override
Widget build(BuildContext context) => LayoutBuilder(
builder: (context, constraints) {
final isWidthLarger =
constraints.maxWidth >= kHabitLargeScreenAdaptWidth;
final isHeightLarger =
constraints.maxHeight >= kHabitLargeScreenAdaptHeight;

if (ignoreWidth && ignoreHeight) {
return builder(context, defaultUiType, child);
} else if (ignoreWidth) {
return builder(
context,
isHeightLarger ? UiLayoutType.l : UiLayoutType.s,
child,
);
} else if (ignoreHeight) {
return builder(
context,
isWidthLarger ? UiLayoutType.l : UiLayoutType.s,
child,
);
} else {
return builder(
context,
isWidthLarger && isHeightLarger ? UiLayoutType.l : UiLayoutType.s,
child,
);
}
},
);
}
5 changes: 4 additions & 1 deletion lib/view/for_app_sync/app_sync_config_subgroup.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ import '_widget.dart';
class AppSyncConfigSubgroup extends StatelessWidget {
final bool enabled;
final AppSyncServer? serverConfig;
final VoidCallback? onConfigPressed;

const AppSyncConfigSubgroup({
super.key,
required this.enabled,
required this.serverConfig,
this.onConfigPressed,
});

@override
Expand All @@ -34,7 +36,8 @@ class AppSyncConfigSubgroup extends StatelessWidget {
expand: enabled,
child: Column(
children: [
AppSyncSummaryTile(serverConfig: serverConfig),
AppSyncSummaryTile(
serverConfig: serverConfig, onPressed: onConfigPressed),
],
),
);
Expand Down
3 changes: 3 additions & 0 deletions lib/view/for_app_sync/app_sync_summary_tile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ import '../../model/app_sync_server.dart';

class AppSyncSummaryTile extends StatelessWidget {
final AppSyncServer? serverConfig;
final VoidCallback? onPressed;

const AppSyncSummaryTile({
super.key,
required this.serverConfig,
this.onPressed,
});

IconData? getSubTitleLeading(BuildContext context) =>
Expand Down Expand Up @@ -51,6 +53,7 @@ class AppSyncSummaryTile extends StatelessWidget {
Text("Current: ${serverConfig.name}"),
])
: Text("Not Configured."),
onTap: onPressed,
);
}
}
16 changes: 16 additions & 0 deletions lib/view/for_app_sync_server_editor/_widget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright 2025 Fries_I23
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

export './app_sync_server_type.dart';
export './page_providers.dart';
52 changes: 52 additions & 0 deletions lib/view/for_app_sync_server_editor/app_sync_server_type.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2025 Fries_I23
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import '../../l10n/localizations.g.dart';
import '../../model/app_sync_server.dart';
import '../../provider/app_sync_server_form.dart';

class AppSyncServerTypeMenu extends StatelessWidget {
final double? width;

const AppSyncServerTypeMenu({super.key, this.width});

String getName(AppSyncServerType type, [L10n? l10n]) {
switch (type) {
case AppSyncServerType.webdav:
return 'WebDAV';
default:
return 'Unknown';
}
}

@override
Widget build(BuildContext context) {
final l10n = L10n.of(context);
return DropdownMenu<AppSyncServerType>(
width: width,
enableSearch: false,
requestFocusOnTap: false,
initialSelection: context.watch<AppSyncServerFormViewModel>().type,
dropdownMenuEntries: AppSyncServerType.values
.where((e) => e != AppSyncServerType.unknown)
.map((e) => DropdownMenuEntry(value: e, label: getName(e, l10n)))
.toList(),
onSelected: (value) =>
context.read<AppSyncServerFormViewModel>().type = value!,
);
}
}
Loading

0 comments on commit 390b18c

Please sign in to comment.