Skip to content

Commit

Permalink
feat: add sync interval (indev)
Browse files Browse the repository at this point in the history
  • Loading branch information
FriesI23 committed Feb 2, 2025
1 parent 3fc7ca8 commit 8c0cb50
Show file tree
Hide file tree
Showing 9 changed files with 140 additions and 39 deletions.
2 changes: 2 additions & 0 deletions lib/common/consts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

import '../model/app_reminder_config.dart';
import '../model/app_sync_options.dart';
import '../model/habit_display.dart';
import '../model/habit_form.dart';
import '../theme/color.dart';
Expand Down Expand Up @@ -85,6 +86,7 @@ const defaultAppReminder = AppReminderConfig.off;
const defaultAppSyncTimeout = Duration(seconds: 60);
const defaultAppSyncConnectTimeout = Duration(seconds: 10);
const int? defaultAppSyncConnectRetryCount = null; // null for infinity
const defaultAppSyncFetchInterval = AppSyncFetchInterval.manual;
//#endregion

//#region habit-field
Expand Down
38 changes: 38 additions & 0 deletions lib/model/app_sync_options.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// 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 '../common/enums.dart';

enum AppSyncFetchInterval implements EnumWithDBCode {
manual(null),
minute5(Duration(minutes: 5)),
minute15(Duration(minutes: 15)),
minute30(Duration(minutes: 30)),
hour1(Duration(hours: 1));

final Duration? t;

const AppSyncFetchInterval(this.t);

@override
int get dbCode => t?.inSeconds ?? -1;

static AppSyncFetchInterval? getFromDBCode(int dbCode,
{AppSyncFetchInterval? withDefault = AppSyncFetchInterval.manual}) {
for (var value in AppSyncFetchInterval.values) {
if (value.dbCode == dbCode) return value;
}
return withDefault;
}
}
41 changes: 41 additions & 0 deletions lib/persistent/profile/handler/app_sync.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@

import 'dart:convert';

import '../../../common/consts.dart';
import '../../../common/types.dart';
import '../../../model/app_sync_options.dart';
import '../../../model/app_sync_server.dart';
import '../converter.dart';
import '../profile_helper.dart';
Expand All @@ -26,6 +28,45 @@ class AppSyncSwitchHandler extends ProfileHelperCovertToBoolHandler<bool> {
String get key => 'enableSync';
}

class AppSyncFetchIntervalHandler
extends ProfileHelperCovertToIntHandler<AppSyncFetchInterval> {
AppSyncFetchIntervalHandler(super.pref)
: super(codec: const AppSyncFetchIntervalCodec());

@override
String get key => 'syncFetchInterval';
}

final class AppSyncFetchIntervalCodec extends Codec<AppSyncFetchInterval, int> {
const AppSyncFetchIntervalCodec();

@override
Converter<int, AppSyncFetchInterval> get decoder =>
const _AppSyncFetchIntervalDecoder();

@override
Converter<AppSyncFetchInterval, int> get encoder =>
const _AppSyncFetchIntervalEncoder();
}

final class _AppSyncFetchIntervalEncoder
extends Converter<AppSyncFetchInterval, int> {
const _AppSyncFetchIntervalEncoder();

@override
int convert(AppSyncFetchInterval input) => input.dbCode;
}

final class _AppSyncFetchIntervalDecoder
extends Converter<int, AppSyncFetchInterval> {
const _AppSyncFetchIntervalDecoder();

@override
AppSyncFetchInterval convert(int input) =>
AppSyncFetchInterval.getFromDBCode(input,
withDefault: defaultAppSyncFetchInterval)!;
}

class AppSyncServerConfigHandler
extends ProfileHelperCovertToJsonHandler<AppSyncServer?> {
const AppSyncServerConfigHandler(super.pref,
Expand Down
17 changes: 16 additions & 1 deletion lib/provider/app_sync.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import 'package:flutter/foundation.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

import '../common/consts.dart';
import '../model/app_sync_options.dart';
import '../model/app_sync_server.dart';
import '../persistent/profile/handler/app_sync.dart';
import '../persistent/profile_provider.dart';
Expand All @@ -25,6 +27,7 @@ class AppSyncViewModel
implements ProviderMounted {
bool _mounted = true;
AppSyncSwitchHandler? _switch;
AppSyncFetchIntervalHandler? _interval;
AppSyncServerConfigHandler? _serverConfig;

@override
Expand All @@ -40,6 +43,7 @@ class AppSyncViewModel
void updateProfile(ProfileViewModel newProfile) {
super.updateProfile(newProfile);
_switch = newProfile.getHandler<AppSyncSwitchHandler>();
_interval = newProfile.getHandler<AppSyncFetchIntervalHandler>();
_serverConfig = newProfile.getHandler<AppSyncServerConfigHandler>();
}

Expand All @@ -48,7 +52,18 @@ class AppSyncViewModel
Future<void> setSyncSwitch(bool value, {bool listen = true}) async {
if (_switch?.get() != value) {
await _switch?.set(value);
notifyListeners();
if (listen) notifyListeners();
}
}

AppSyncFetchInterval get fetchInterval =>
_interval?.get() ?? defaultAppSyncFetchInterval;

Future<void> setFetchInterval(AppSyncFetchInterval value,
{bool listen = true}) async {
if (_interval?.get() != value) {
await _interval?.set(value);
if (listen) notifyListeners();
}
}

Expand Down
1 change: 1 addition & 0 deletions lib/view/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class App extends StatelessWidget {
AppLanguageProfileHanlder.new,
AppSyncSwitchHandler.new,
AppSyncServerConfigHandler.new,
AppSyncFetchIntervalHandler.new,
];

const App({super.key});
Expand Down
2 changes: 1 addition & 1 deletion lib/view/for_app_sync/_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@
// See the License for the specific language governing permissions and
// limitations under the License.

export './app_sync_config_subgroup.dart';
export './app_sync_interval_tile.dart' show AppSyncIntervalTile;
export './app_sync_summary_tile.dart';
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,13 @@

import 'package:flutter/material.dart';

import '../../component/widget.dart';
import '../../model/app_sync_server.dart';
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,
});
class AppSyncIntervalTile extends StatelessWidget {
const AppSyncIntervalTile({super.key});

@override
Widget build(BuildContext context) {
return ExpandedSection(
expand: enabled,
child: Column(
children: [
AppSyncSummaryTile(
serverConfig: serverConfig, onPressed: onConfigPressed),
],
),
return ListTile(
title: const Text("Fetch Interval"),
);
}
}
17 changes: 10 additions & 7 deletions lib/view/for_app_sync/app_sync_summary_tile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,36 +14,39 @@

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

import '../../model/app_sync_server.dart';
import '../../provider/app_sync.dart';

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

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

IconData? getSubTitleLeading(BuildContext context) =>
IconData? getSubTitleLeading(
BuildContext context, AppSyncServer? serverConfig) =>
switch (serverConfig?.type) {
AppSyncServerType.webdav => MdiIcons.cloudOutline,
AppSyncServerType.unknown => null,
_ => Icons.warning,
};

IconData? getTrailing(BuildContext context) => switch (serverConfig?.type) {
IconData? getTrailing(BuildContext context, AppSyncServer? serverConfig) =>
switch (serverConfig?.type) {
!= null => Icons.edit,
_ => Icons.add,
};

@override
Widget build(BuildContext context) {
final serverConfig = this.serverConfig;
final trailingData = getTrailing(context);
final subtileLeading = getSubTitleLeading(context);
final serverConfig = context
.select<AppSyncViewModel, AppSyncServer?>((vm) => vm.serverConfig);
final trailingData = getTrailing(context, serverConfig);
final subtileLeading = getSubTitleLeading(context, serverConfig);
return ListTile(
trailing: trailingData != null ? Icon(trailingData) : null,
title: Text("Sync Server"),
Expand Down
34 changes: 27 additions & 7 deletions lib/view/page_app_sync.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import '../component/widgets/page_back_button.dart';
import '../component/widget.dart';
import '../logging/helper.dart';
import '../model/app_sync_server.dart';
import '../provider/app_developer.dart';
import '../provider/app_sync.dart';
import 'for_app_sync/_widget.dart';
Expand Down Expand Up @@ -105,12 +104,11 @@ final class _AppSyncView extends State<AppSyncView> {
),
),
const Divider(),
Selector<AppSyncViewModel, ({bool enabled, AppSyncServer? config})>(
selector: (ctx, v) => (enabled: v.enabled, config: v.serverConfig),
Selector<AppSyncViewModel, bool>(
selector: (ctx, v) => v.enabled,
shouldRebuild: (previous, next) => previous != next,
builder: (context, value, child) => AppSyncConfigSubgroup(
enabled: value.enabled,
serverConfig: value.config,
builder: (context, value, child) => _AppSyncConfigSubgroup(
enabled: value,
onConfigPressed: _onServerConfigPressed,
),
),
Expand All @@ -124,6 +122,28 @@ final class _AppSyncView extends State<AppSyncView> {
}
}

class _AppSyncConfigSubgroup extends StatelessWidget {
final bool enabled;
final VoidCallback? onConfigPressed;

const _AppSyncConfigSubgroup({
required this.enabled,
this.onConfigPressed,
});

@override
Widget build(BuildContext context) {
return ExpandedSection(
expand: enabled,
child: Column(
children: [
AppSyncSummaryTile(onPressed: onConfigPressed),
],
),
);
}
}

class _DebugShowTile extends StatelessWidget {
const _DebugShowTile();

Expand Down

0 comments on commit 8c0cb50

Please sign in to comment.