fix: settings ui improvements (#5590)

* fix: settings ui improvements

* fix: replace placeholder + fix open folder

* fix: collapse sidebar button on windows

* test: fix tests after changes

* test: missed type cast
This commit is contained in:
Mathias Mogensen 2024-06-20 21:01:20 +02:00 committed by GitHub
parent d8b32168a9
commit 7586a0ed48
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 268 additions and 283 deletions

View File

@ -1,5 +1,5 @@
import 'package:appflowy/workspace/application/settings/settings_dialog_bloc.dart';
import 'package:flutter/material.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
@ -17,25 +17,25 @@ void main() {
await tester.openSettingsPage(SettingsPage.notifications);
await tester.pumpAndSettle();
final switchFinder = find.byType(Switch).first;
final toggleFinder = find.byType(Toggle).first;
// Defaults to enabled
Switch switchWidget = tester.widget(switchFinder);
expect(switchWidget.value, true);
Toggle toggleWidget = tester.widget(toggleFinder);
expect(toggleWidget.value, true);
// Disable
await tester.tap(switchFinder);
await tester.tap(toggleFinder);
await tester.pumpAndSettle();
switchWidget = tester.widget(switchFinder);
expect(switchWidget.value, false);
toggleWidget = tester.widget(toggleFinder);
expect(toggleWidget.value, false);
// Enable again
await tester.tap(switchFinder);
await tester.tap(toggleFinder);
await tester.pumpAndSettle();
switchWidget = tester.widget(switchFinder);
expect(switchWidget.value, true);
toggleWidget = tester.widget(toggleFinder);
expect(toggleWidget.value, true);
});
});
}

View File

@ -1,15 +1,16 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/shared/window_title_bar.dart';
import 'package:appflowy/util/theme_extension.dart';
import 'package:appflowy/workspace/application/home/home_setting_bloc.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
import 'package:flowy_infra_ui/style_widget/hover.dart';
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class CocoaWindowChannel {
@ -122,15 +123,21 @@ class MoveWindowDetectorState extends State<MoveWindowDetector> {
return FlowyTooltip(
richMessage: textSpan,
child: FlowyIconButton(
hoverColor: Colors.transparent,
onPressed: () => context
child: Listener(
behavior: HitTestBehavior.translucent,
onPointerDown: (_) => context
.read<HomeSettingBloc>()
.add(const HomeSettingEvent.collapseMenu()),
iconPadding: const EdgeInsets.all(4.0),
icon: context.read<HomeSettingBloc>().state.isMenuCollapsed
? const FlowySvg(FlowySvgs.show_menu_s)
: const FlowySvg(FlowySvgs.hide_menu_m),
child: FlowyHover(
child: Container(
width: 24,
padding: const EdgeInsets.all(4),
child: const RotatedBox(
quarterTurns: 2,
child: FlowySvg(FlowySvgs.hide_menu_s),
),
),
),
),
);
}

View File

@ -1,3 +1,5 @@
import 'package:flutter/material.dart';
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database/application/database_controller.dart';
@ -5,12 +7,10 @@ import 'package:appflowy/plugins/database/application/setting/property_bloc.dart
import 'package:appflowy/plugins/database/calendar/application/calendar_setting_bloc.dart';
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle_style.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
/// Widget that displays a list of settings that alters the appearance of the
@ -325,7 +325,6 @@ Widget _toggleItem({
Toggle(
value: value,
onChanged: (value) => onToggle(!value),
style: ToggleStyle.big,
padding: EdgeInsets.zero,
),
],

View File

@ -1,5 +1,7 @@
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database/application/field/field_controller.dart';
@ -11,12 +13,10 @@ import 'package:appflowy/plugins/database/grid/presentation/widgets/common/type_
import 'package:appflowy/util/field_type_extension.dart';
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle_style.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'field_type_list.dart';
@ -258,7 +258,6 @@ enum FieldAction {
onChanged: (_) => context
.read<FieldEditorBloc>()
.add(const FieldEditorEvent.toggleWrapCellContent()),
style: ToggleStyle.big,
padding: EdgeInsets.zero,
);
}

View File

@ -1,12 +1,12 @@
import 'package:flutter/material.dart';
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle_style.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
class DateFormatButton extends StatelessWidget {
const DateFormatButton({
@ -248,7 +248,6 @@ class IncludeTimeButton extends StatelessWidget {
Toggle(
value: value,
onChanged: onChanged,
style: ToggleStyle.big,
padding: EdgeInsets.zero,
),
],

View File

@ -9,7 +9,6 @@ import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
import 'package:appflowy/plugins/database/grid/presentation/widgets/common/type_option_separator.dart';
import 'package:appflowy/util/field_type_extension.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle_style.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
import 'package:collection/collection.dart';
import 'package:easy_localization/easy_localization.dart';
@ -74,7 +73,6 @@ class DatabaseGroupList extends StatelessWidget {
value: !state.layoutSettings.hideUngroupedColumn,
onChanged: (value) =>
_updateLayoutSettings(state.layoutSettings, value),
style: ToggleStyle.big,
padding: EdgeInsets.zero,
),
],

View File

@ -22,7 +22,6 @@ import 'package:appflowy/workspace/presentation/settings/widgets/files/settings_
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:dotted_border/dotted_border.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/file_picker/file_picker_service.dart';
import 'package:flowy_infra/theme_extension.dart';
@ -288,65 +287,22 @@ class _ImportDataFieldState extends State<_ImportDataField> {
(_) => _showToast(LocaleKeys.settings_menu_importFailed.tr()),
),
builder: (context, state) {
return DottedBorder(
radius: const Radius.circular(8),
dashPattern: const [2, 2],
borderType: BorderType.RRect,
color: Theme.of(context).colorScheme.primary,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
// When dragging files are enabled
// FlowyText.regular('Drag file here or'),
// const VSpace(8),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: 42,
child: FlowyTextButton(
LocaleKeys.settings_manageDataPage_importData_action
.tr(),
padding: const EdgeInsets.symmetric(
horizontal: 24,
vertical: 12,
),
fontWeight: FontWeight.w600,
radius: BorderRadius.circular(12),
fillColor: Theme.of(context).colorScheme.primary,
hoverColor: const Color(0xFF005483),
fontHoverColor: Colors.white,
return SingleSettingAction(
label:
LocaleKeys.settings_manageDataPage_importData_description.tr(),
labelMaxLines: 2,
buttonLabel:
LocaleKeys.settings_manageDataPage_importData_action.tr(),
onPressed: () async {
final path = await getIt<FilePickerService>()
.getDirectoryPath();
final path = await getIt<FilePickerService>().getDirectoryPath();
if (path == null || !context.mounted) {
return;
}
context.read<SettingFileImportBloc>().add(
SettingFileImportEvent
.importAppFlowyDataFolder(
path,
),
);
context
.read<SettingFileImportBloc>()
.add(SettingFileImportEvent.importAppFlowyDataFolder(path));
},
),
),
],
),
const VSpace(8),
FlowyText.regular(
LocaleKeys.settings_manageDataPage_importData_description
.tr(),
// 'Supported filetypes:\nCSV, Notion, Text, and Markdown',
maxLines: 3,
lineHeight: 1.5,
textAlign: TextAlign.center,
),
],
),
),
);
},
),
@ -496,7 +452,7 @@ class _DataPathActions extends StatelessWidget {
label:
LocaleKeys.settings_manageDataPage_dataStorage_actions_open.tr(),
icon: const FlowySvg(FlowySvgs.folder_m, size: Size.square(20)),
onPressed: () => afLaunchUrlString('file://$currentPath'),
onPressed: () => afLaunchUrl(Uri.file(currentPath)),
),
],
);

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/util/theme_extension.dart';
import 'package:appflowy/workspace/application/settings/plan/settings_plan_bloc.dart';
import 'package:appflowy/workspace/application/settings/plan/workspace_subscription_ext.dart';
import 'package:appflowy/workspace/presentation/settings/shared/settings_alert_dialog.dart';
@ -44,6 +45,8 @@ class _SettingsPlanComparisonDialogState
@override
Widget build(BuildContext context) {
final isLM = Theme.of(context).isLightMode;
return BlocListener<SettingsPlanBloc, SettingsPlanState>(
listener: (context, state) {
final readyState = state.mapOrNull(ready: (state) => state);
@ -64,15 +67,11 @@ class _SettingsPlanComparisonDialogState
),
),
),
title:
LocaleKeys.settings_comparePlanDialog_paymentSuccess_title.tr(
args: [readyState.subscription.label],
),
title: LocaleKeys.settings_comparePlanDialog_paymentSuccess_title
.tr(args: [readyState.subscription.label]),
subtitle: LocaleKeys
.settings_comparePlanDialog_paymentSuccess_description
.tr(
args: [readyState.subscription.label],
),
.tr(args: [readyState.subscription.label]),
hideCancelButton: true,
confirm: Navigator.of(context).pop,
confirmLabel: LocaleKeys.button_close.tr(),
@ -96,6 +95,7 @@ class _SettingsPlanComparisonDialogState
FlowyText.semibold(
LocaleKeys.settings_comparePlanDialog_title.tr(),
fontSize: 24,
color: AFThemeExtension.of(context).strongText,
),
const Spacer(),
GestureDetector(
@ -108,13 +108,14 @@ class _SettingsPlanComparisonDialogState
child: FlowySvg(
FlowySvgs.m_close_m,
size: const Size.square(20),
color: Theme.of(context).colorScheme.outline,
color: AFThemeExtension.of(context).strongText,
),
),
),
],
),
),
const VSpace(16),
Flexible(
child: SingleChildScrollView(
controller: horizontalController,
@ -140,7 +141,7 @@ class _SettingsPlanComparisonDialogState
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const VSpace(26),
const VSpace(30),
SizedBox(
height: 100,
child: FlowyText.semibold(
@ -149,7 +150,9 @@ class _SettingsPlanComparisonDialogState
.tr(),
fontSize: 24,
maxLines: 2,
color: const Color(0xFF5C3699),
color: isLM
? const Color(0xFF5C3699)
: const Color(0xFFE8E0FF),
),
),
const SizedBox(height: 64),
@ -281,17 +284,18 @@ class _PlanTable extends StatelessWidget {
@override
Widget build(BuildContext context) {
final highlightPlan = !isCurrent && !canDowngrade && canUpgrade;
final isLM = Theme.of(context).isLightMode;
return Container(
width: 210,
width: 215,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24),
gradient: !highlightPlan
? null
: const LinearGradient(
: LinearGradient(
colors: [
Color(0xFF251D37),
Color(0xFF7547C0),
isLM ? const Color(0xFF251D37) : const Color(0xFF7459AD),
isLM ? const Color(0xFF7547C0) : const Color(0xFFDDC8FF),
],
),
),
@ -311,6 +315,7 @@ class _PlanTable extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (isCurrent) const _CurrentBadge(),
const VSpace(4),
_Heading(
title: title,
description: description,
@ -376,14 +381,16 @@ class _CurrentBadge extends StatelessWidget {
height: 22,
width: 72,
decoration: BoxDecoration(
color: const Color(0xFF4F3F5F),
color: Theme.of(context).isLightMode
? const Color(0xFF4F3F5F)
: const Color(0xFFE8E0FF),
borderRadius: BorderRadius.circular(4),
),
child: Center(
child: FlowyText.medium(
LocaleKeys.settings_comparePlanDialog_current.tr(),
fontSize: 12,
color: Colors.white,
color: Theme.of(context).isLightMode ? Colors.white : Colors.black,
),
),
);
@ -417,22 +424,28 @@ class _ComparisonCell extends StatelessWidget {
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (icon != null) ...[
FlowySvg(icon!),
FlowySvg(
icon!,
color: AFThemeExtension.of(context).strongText,
),
] else ...[
Expanded(
child: FlowyText.medium(
label,
lineHeight: 1.2,
color: AFThemeExtension.of(context).strongText,
),
),
],
if (tooltip != null)
FlowyTooltip(
message: tooltip,
child: const FlowySvg(FlowySvgs.information_s),
child: FlowySvg(
FlowySvgs.information_s,
color: AFThemeExtension.of(context).strongText,
),
),
],
),
@ -457,9 +470,8 @@ class _ActionButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
final isLM = Theme.of(context).brightness == Brightness.light;
final isLM = Theme.of(context).isLightMode;
final gradientBorder = useGradientBorder && isLM;
return SizedBox(
height: 56,
child: Row(
@ -475,25 +487,17 @@ class _ActionButton extends StatelessWidget {
child: _drawGradientBorder(
isLM: isLM,
child: Container(
height: gradientBorder ? 36 : 40,
width: gradientBorder ? 148 : 152,
height: 36,
width: 148,
decoration: BoxDecoration(
color: useGradientBorder
? Theme.of(context).cardColor
: Colors.transparent,
border: Border.all(
color: gradientBorder
? Colors.transparent
: AFThemeExtension.of(context).textColor,
),
borderRadius:
BorderRadius.circular(gradientBorder ? 14 : 16),
border: Border.all(color: Colors.transparent),
borderRadius: BorderRadius.circular(14),
),
child: Center(
child: _drawText(
label,
isLM,
),
child: _drawText(label, isLM),
),
),
),
@ -511,6 +515,7 @@ class _ActionButton extends StatelessWidget {
fontSize: 14,
lineHeight: 1.2,
fontWeight: useGradientBorder ? FontWeight.w600 : FontWeight.w500,
color: const Color(0xFFC49BEC),
);
if (!useGradientBorder || !isLM) {
@ -532,19 +537,15 @@ class _ActionButton extends StatelessWidget {
}
Widget _drawGradientBorder({required bool isLM, required Widget child}) {
if (!useGradientBorder || !isLM) {
return child;
}
return Container(
padding: const EdgeInsets.all(2),
decoration: BoxDecoration(
gradient: const LinearGradient(
transform: GradientRotation(-1.2),
stops: [0.4, 1],
gradient: LinearGradient(
transform: const GradientRotation(-1.2),
stops: const [0.4, 1],
colors: [
Color(0xFF251D37),
Color(0xFF7547C0),
isLM ? const Color(0xFF251D37) : const Color(0xFF7459AD),
isLM ? const Color(0xFF7547C0) : const Color(0xFFDDC8FF),
],
),
borderRadius: BorderRadius.circular(16),
@ -582,7 +583,9 @@ class _Heading extends StatelessWidget {
fontSize: 24,
color: isPrimary
? AFThemeExtension.of(context).strongText
: const Color(0xFF5C3699),
: Theme.of(context).isLightMode
? const Color(0xFF5C3699)
: const Color(0xFFC49BEC),
),
if (description != null && description!.isNotEmpty) ...[
const VSpace(4),

View File

@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/util/int64_extension.dart';
import 'package:appflowy/util/theme_extension.dart';
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
import 'package:appflowy/workspace/application/settings/date_time/date_format_ext.dart';
import 'package:appflowy/workspace/application/settings/plan/settings_plan_bloc.dart';
@ -12,7 +13,6 @@ import 'package:appflowy/workspace/presentation/settings/pages/settings_plan_com
import 'package:appflowy/workspace/presentation/settings/shared/flowy_gradient_button.dart';
import 'package:appflowy/workspace/presentation/settings/shared/settings_body.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle_style.dart';
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-user/workspace.pb.dart';
import 'package:easy_localization/easy_localization.dart';
@ -62,8 +62,7 @@ class SettingsPlanView extends StatelessWidget {
return ErrorWidget.withDetails(message: 'Something went wrong!');
},
ready: (state) {
return SettingsBody(
ready: (state) => SettingsBody(
autoSeparate: false,
title: LocaleKeys.settings_planPage_title.tr(),
children: [
@ -73,8 +72,7 @@ class SettingsPlanView extends StatelessWidget {
),
_CurrentPlanBox(subscription: state.subscription),
],
);
},
),
);
},
),
@ -266,13 +264,16 @@ class _ProConItem extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 24,
width: 24,
width: 18,
child: FlowySvg(
isPro ? FlowySvgs.check_m : FlowySvgs.close_s,
color: isPro ? null : const Color(0xFF900000),
isPro ? FlowySvgs.check_m : FlowySvgs.close_error_s,
size: const Size.square(18),
color: isPro
? AFThemeExtension.of(context).strongText
: const Color(0xFF900000),
),
),
const HSpace(4),
@ -415,7 +416,7 @@ class _ToggleMoreState extends State<_ToggleMore> {
@override
Widget build(BuildContext context) {
final isLM = Brightness.light == Theme.of(context).brightness;
final isLM = Theme.of(context).isLightMode;
final primaryColor =
isLM ? const Color(0xFF653E8C) : const Color(0xFFE8E2EE);
final secondaryColor =
@ -426,7 +427,6 @@ class _ToggleMoreState extends State<_ToggleMore> {
Toggle(
value: toggleValue,
padding: EdgeInsets.zero,
style: ToggleStyle.big,
onChanged: (_) {
setState(() => toggleValue = !toggleValue);

View File

@ -31,7 +31,6 @@ import 'package:appflowy/workspace/presentation/settings/shared/settings_radio_s
import 'package:appflowy/workspace/presentation/settings/shared/single_setting_action.dart';
import 'package:appflowy/workspace/presentation/settings/widgets/theme_upload/theme_upload_view.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle_style.dart';
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:easy_localization/easy_localization.dart';
@ -417,7 +416,6 @@ class EnableRTLItemsSwitcher extends StatelessWidget {
),
const HSpace(16),
Toggle(
style: ToggleStyle.big,
value: context
.watch<AppearanceSettingsCubit>()
.state
@ -564,7 +562,6 @@ class _TimeFormatSwitcher extends StatelessWidget {
),
const HSpace(16),
Toggle(
style: ToggleStyle.big,
value: context.watch<AppearanceSettingsCubit>().state.timeFormat ==
UserTimeFormatPB.TwentyFourHour,
onChanged: (value) =>

View File

@ -1,9 +1,10 @@
import 'package:flutter/material.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/user/presentation/screens/sign_in_screen/widgets/sign_in_or_logout_button.dart';
import 'package:appflowy_editor/appflowy_editor.dart' show PlatformExtension;
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
class RestartButton extends StatelessWidget {
const RestartButton({
@ -17,7 +18,7 @@ class RestartButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
final List<Widget> children = [_buildRestartButton()];
final List<Widget> children = [_buildRestartButton(context)];
if (showRestartHint) {
children.add(
Padding(
@ -33,25 +34,43 @@ class RestartButton extends StatelessWidget {
return Column(children: children);
}
Widget _buildRestartButton() {
Widget _buildRestartButton(BuildContext context) {
if (PlatformExtension.isDesktopOrWeb) {
return Row(
children: [
FlowyButton(
isSelected: true,
useIntrinsicWidth: true,
margin: const EdgeInsets.symmetric(
horizontal: 30,
vertical: 10,
SizedBox(
height: 42,
child: FlowyTextButton(
LocaleKeys.settings_manageDataPage_dataStorage_actions_change
.tr(),
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
fontWeight: FontWeight.w600,
radius: BorderRadius.circular(12),
fillColor: Theme.of(context).colorScheme.primary,
hoverColor: const Color(0xFF005483),
fontHoverColor: Colors.white,
onPressed: onClick,
),
text: FlowyText(
LocaleKeys.settings_menu_restartApp.tr(),
),
onTap: onClick,
),
const Spacer(),
],
);
// Row(
// children: [
// FlowyButton(
// isSelected: true,
// useIntrinsicWidth: true,
// margin: const EdgeInsets.symmetric(
// horizontal: 30,
// vertical: 10,
// ),
// text: FlowyText(
// LocaleKeys.settings_menu_restartApp.tr(),
// ),
// onTap: onClick,
// ),
// const Spacer(),
// ],
// );
} else {
return MobileSignInOrLogoutButton(
labelText: LocaleKeys.settings_menu_restartApp.tr(),

View File

@ -10,7 +10,6 @@ import 'package:appflowy/workspace/application/settings/appflowy_cloud_urls_bloc
import 'package:appflowy/workspace/presentation/settings/widgets/_restart_app_button.dart';
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle_style.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-user/user_setting.pb.dart';
@ -317,7 +316,6 @@ class AppFlowyCloudEnableSync extends StatelessWidget {
FlowyText.medium(LocaleKeys.settings_menu_enableSync.tr()),
const Spacer(),
Toggle(
style: ToggleStyle.big,
value: state.setting.enableSync,
onChanged: (value) => context
.read<AppFlowyCloudSettingBloc>()

View File

@ -1,3 +1,5 @@
import 'package:flutter/material.dart';
import 'package:appflowy/env/cloud_env.dart';
import 'package:appflowy/env/env.dart';
import 'package:appflowy/generated/flowy_svgs.g.dart';
@ -6,16 +8,16 @@ import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/workspace/application/settings/cloud_setting_bloc.dart';
import 'package:appflowy/workspace/presentation/settings/shared/af_dropdown_menu_entry.dart';
import 'package:appflowy/workspace/presentation/settings/shared/settings_body.dart';
import 'package:appflowy/workspace/presentation/settings/shared/settings_dropdown.dart';
import 'package:appflowy/workspace/presentation/settings/widgets/setting_local_cloud.dart';
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:collection/collection.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/theme_extension.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
@ -41,6 +43,7 @@ class SettingCloud extends StatelessWidget {
builder: (context, state) {
return SettingsBody(
title: LocaleKeys.settings_menu_cloudSettings.tr(),
autoSeparate: false,
children: [
if (Env.enableCustomCloud)
Row(
@ -50,12 +53,14 @@ class SettingCloud extends StatelessWidget {
LocaleKeys.settings_menu_cloudServerType.tr(),
),
),
CloudTypeSwitcher(
Flexible(
child: CloudTypeSwitcher(
cloudType: state.cloudType,
onSelected: (type) => context
.read<CloudSettingBloc>()
.add(CloudSettingEvent.updateCloudType(type)),
),
),
],
),
_viewFromCloudType(state.cloudType),
@ -74,21 +79,13 @@ class SettingCloud extends StatelessWidget {
Widget _viewFromCloudType(AuthenticatorType cloudType) {
switch (cloudType) {
case AuthenticatorType.local:
return SettingLocalCloud(
restartAppFlowy: restartAppFlowy,
);
return SettingLocalCloud(restartAppFlowy: restartAppFlowy);
case AuthenticatorType.supabase:
return SettingSupabaseCloudView(
restartAppFlowy: restartAppFlowy,
);
return SettingSupabaseCloudView(restartAppFlowy: restartAppFlowy);
case AuthenticatorType.appflowyCloud:
return AppFlowyCloudViewSetting(
restartAppFlowy: restartAppFlowy,
);
return AppFlowyCloudViewSetting(restartAppFlowy: restartAppFlowy);
case AuthenticatorType.appflowyCloudSelfHost:
return CustomAppFlowyCloudView(
restartAppFlowy: restartAppFlowy,
);
return CustomAppFlowyCloudView(restartAppFlowy: restartAppFlowy);
case AuthenticatorType.appflowyCloudDevelop:
return AppFlowyCloudViewSetting(
serverURL: "http://localhost",
@ -122,46 +119,42 @@ class CloudTypeSwitcher extends StatelessWidget {
return isDevelopMode || element != AuthenticatorType.appflowyCloudDevelop;
}).toList();
return PlatformExtension.isDesktopOrWeb
? AppFlowyPopover(
direction: PopoverDirection.bottomWithRightAligned,
child: FlowyTextButton(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 6),
titleFromCloudType(cloudType),
fontColor: AFThemeExtension.of(context).onBackground,
fillColor: Colors.transparent,
onPressed: () {},
? SettingsDropdown(
selectedOption: cloudType,
onChanged: (type) {
if (type != cloudType) {
NavigatorAlertDialog(
title: LocaleKeys.settings_menu_changeServerTip.tr(),
confirm: () async {
onSelected(type);
},
hideCancelButton: true,
).show(context);
}
},
options: values
.map(
(type) => buildDropdownMenuEntry(
context,
value: type,
label: titleFromCloudType(type),
),
popupBuilder: (BuildContext context) {
return ListView.builder(
shrinkWrap: true,
itemBuilder: (context, index) {
return CloudTypeItem(
cloudType: values[index],
currentCloudtype: cloudType,
onSelected: onSelected,
);
},
itemCount: values.length,
);
},
)
.toList(),
)
: FlowyButton(
text: FlowyText(
titleFromCloudType(cloudType),
),
text: FlowyText(titleFromCloudType(cloudType)),
useIntrinsicWidth: true,
rightIcon: const Icon(
Icons.chevron_right,
),
onTap: () {
showMobileBottomSheet(
onTap: () => showMobileBottomSheet(
context,
showHeader: true,
showDragHandle: true,
showDivider: false,
title: LocaleKeys.settings_menu_cloudServerType.tr(),
builder: (context) {
return Column(
builder: (context) => Column(
children: values
.mapIndexed(
(i, e) => FlowyOptionTile.checkbox(
@ -175,10 +168,8 @@ class CloudTypeSwitcher extends StatelessWidget {
),
)
.toList(),
);
},
);
},
),
),
);
}
}

View File

@ -4,6 +4,7 @@ import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/workspace/application/settings/notifications/notification_settings_cubit.dart';
import 'package:appflowy/workspace/presentation/settings/shared/setting_list_tile.dart';
import 'package:appflowy/workspace/presentation/settings/shared/settings_body.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@ -23,10 +24,8 @@ class SettingsNotificationsView extends StatelessWidget {
hint: LocaleKeys.settings_notifications_enableNotifications_hint
.tr(),
trailing: [
Switch(
Toggle(
value: state.isNotificationsEnabled,
splashRadius: 0,
activeColor: Theme.of(context).colorScheme.primary,
onChanged: (value) => context
.read<NotificationSettingsCubit>()
.toggleNotificationsEnabled(),
@ -40,10 +39,8 @@ class SettingsNotificationsView extends StatelessWidget {
hint: LocaleKeys.settings_notifications_showNotificationsIcon_hint
.tr(),
trailing: [
Switch(
Toggle(
value: state.isShowNotificationsIconEnabled,
splashRadius: 0,
activeColor: Theme.of(context).colorScheme.primary,
onChanged: (_) => context
.read<NotificationSettingsCubit>()
.toogleShowNotificationIconEnabled(),

View File

@ -1,12 +1,12 @@
import 'package:flutter/material.dart';
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart';
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle_style.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flutter/material.dart';
class EndTimeButton extends StatelessWidget {
const EndTimeButton({
@ -38,7 +38,6 @@ class EndTimeButton extends StatelessWidget {
Toggle(
value: isRange,
onChanged: onChanged,
style: ToggleStyle.big,
padding: EdgeInsets.zero,
),
],

View File

@ -1,13 +1,40 @@
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle_style.dart';
import 'package:flowy_infra/theme_extension.dart';
import 'package:flutter/material.dart';
import 'package:flowy_infra/theme_extension.dart';
class ToggleStyle {
const ToggleStyle({
required this.height,
required this.width,
required this.thumbRadius,
});
const ToggleStyle.big()
: height = 16,
width = 27,
thumbRadius = 14;
const ToggleStyle.small()
: height = 10,
width = 16,
thumbRadius = 8;
const ToggleStyle.mobile()
: height = 24,
width = 42,
thumbRadius = 18;
final double height;
final double width;
final double thumbRadius;
}
class Toggle extends StatelessWidget {
const Toggle({
super.key,
required this.value,
required this.onChanged,
required this.style,
this.style = const ToggleStyle.big(),
this.thumbColor,
this.activeBackgroundColor,
this.inactiveBackgroundColor,
@ -26,7 +53,8 @@ class Toggle extends StatelessWidget {
Widget build(BuildContext context) {
final backgroundColor = value
? activeBackgroundColor ?? Theme.of(context).colorScheme.primary
: activeBackgroundColor ?? AFThemeExtension.of(context).toggleOffFill;
: inactiveBackgroundColor ??
AFThemeExtension.of(context).toggleButtonBGColor;
return GestureDetector(
onTap: () => onChanged(value),
child: Padding(
@ -49,7 +77,7 @@ class Toggle extends StatelessWidget {
height: style.thumbRadius,
width: style.thumbRadius,
decoration: BoxDecoration(
color: thumbColor ?? Theme.of(context).colorScheme.onPrimary,
color: thumbColor ?? Colors.white,
borderRadius: BorderRadius.circular(style.thumbRadius / 2),
),
),

View File

@ -1,20 +0,0 @@
class ToggleStyle {
ToggleStyle({
required this.height,
required this.width,
required this.thumbRadius,
});
final double height;
final double width;
final double thumbRadius;
static ToggleStyle get big =>
ToggleStyle(height: 16, width: 27, thumbRadius: 14);
static ToggleStyle get small =>
ToggleStyle(height: 10, width: 16, thumbRadius: 8);
static ToggleStyle get mobile =>
ToggleStyle(height: 24, width: 42, thumbRadius: 18);
}

View File

@ -126,7 +126,7 @@ class DefaultColorScheme extends FlowyColorScheme {
questionBubbleBG: _darkShader3,
progressBarBGColor: _darkShader3,
toolbarColor: _darkInput,
toggleButtonBGColor: _darkShader1,
toggleButtonBGColor: const Color(0xFF828282),
calendarWeekendBGColor: _darkShader1,
gridRowCountColor: _darkShader5,
);

View File

@ -1,11 +1,12 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flowy_infra/size.dart';
import 'package:flowy_infra_ui/style_widget/hover.dart';
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
import 'package:flowy_infra_ui/widget/ignore_parent_gesture.dart';
import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flutter/material.dart';
class FlowyButton extends StatelessWidget {
final Widget text;
@ -195,7 +196,11 @@ class FlowyTextButton extends StatelessWidget {
children.add(heading!);
children.add(const HSpace(8));
}
children.add(Text(text, overflow: overflow, textAlign: TextAlign.center));
children.add(Text(
text,
overflow: overflow,
textAlign: TextAlign.center,
));
Widget child = Row(
crossAxisAlignment: CrossAxisAlignment.center,
@ -230,6 +235,7 @@ class FlowyTextButton extends StatelessWidget {
fontSize: fontSize,
decoration: decoration,
fontFamily: fontFamily,
height: 1.1,
),
),
backgroundColor: WidgetStateProperty.resolveWith(

View File

@ -0,0 +1,9 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0_4030_10552" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="16" height="16">
<rect width="16" height="16" fill="#D9D9D9"/>
</mask>
<g mask="url(#mask0_4030_10552)">
<path d="M4.26659 12.7942L3.20572 11.7333L6.93905 8.00001L3.20572 4.26668L4.26659 3.20581L7.99992 6.93914L11.7333 3.20581L12.7941 4.26668L9.06078 8.00001L12.7941 11.7333L11.7333 12.7942L7.99992 9.06088L4.26659 12.7942Z" fill="#900000"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 549 B

View File

@ -478,8 +478,8 @@
"importData": {
"title": "Import data",
"tooltip": "Import data from @:appName backups/data folders",
"description": "Copy data from an external @:appName data folder and import it into the current @:appName data folder",
"action": "Browse folder"
"description": "Copy data from an external @:appName data folder",
"action": "Browse file"
},
"encryption": {
"title": "Encryption",
@ -494,7 +494,7 @@
},
"cache": {
"title": "Clear cache",
"description": "If you encounter issues with images not loading or fonts not displaying correctly, try clearing your cache. This action will not remove your user data.",
"description": "Clear app cache, this can help resolve issues like images or fonts not loading. This will not affect your data.",
"dialog": {
"title": "Are you sure?",
"description": "Clearing the cache will cause images and fonts to be re-downloaded on load. This action will not remove or modify your data.",