Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb725d8c06 | ||
|
|
5765e604a7 | ||
|
|
bae67b04a8 |
No files matched your search
@@ -71,7 +71,6 @@ class AIChatPagePlugin extends Plugin {
|
||||
void dispose() {
|
||||
_viewInfoBloc.close();
|
||||
notifier.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,4 +118,7 @@ class AIChatPagePluginWidgetBuilder extends PluginWidgetBuilder
|
||||
|
||||
@override
|
||||
List<NavigationItem> get navigationItems => [this];
|
||||
|
||||
@override
|
||||
EdgeInsets get contentPadding => EdgeInsets.zero;
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/ai_chat/application/chat_bloc.dart';
|
||||
import 'package:appflowy/plugins/ai_chat/presentation/ai_message_bubble.dart';
|
||||
@@ -10,12 +13,10 @@ import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/theme_extension.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_chat_types/flutter_chat_types.dart';
|
||||
import 'package:flutter_chat_ui/flutter_chat_ui.dart' show Chat;
|
||||
import 'package:flutter_chat_types/flutter_chat_types.dart' as types;
|
||||
import 'package:flutter_chat_ui/flutter_chat_ui.dart' show Chat;
|
||||
|
||||
import 'presentation/chat_input.dart';
|
||||
import 'presentation/chat_popmenu.dart';
|
||||
@@ -27,11 +28,11 @@ import 'presentation/message/user_text_message.dart';
|
||||
|
||||
class AIChatUILayout {
|
||||
static EdgeInsets get chatPadding =>
|
||||
isMobile ? EdgeInsets.zero : const EdgeInsets.symmetric(horizontal: 70);
|
||||
isMobile ? EdgeInsets.zero : const EdgeInsets.symmetric(horizontal: 20);
|
||||
|
||||
static EdgeInsets get welcomePagePadding => isMobile
|
||||
? const EdgeInsets.symmetric(horizontal: 20)
|
||||
: const EdgeInsets.symmetric(horizontal: 100);
|
||||
: const EdgeInsets.symmetric(horizontal: 50);
|
||||
|
||||
static double get messageWidthRatio => 0.85;
|
||||
|
||||
@@ -44,7 +45,8 @@ class AIChatUILayout {
|
||||
query.padding.right,
|
||||
query.viewInsets.bottom + query.padding.bottom,
|
||||
)
|
||||
: const EdgeInsets.symmetric(horizontal: 70);
|
||||
: const EdgeInsets.symmetric(horizontal: 50) +
|
||||
const EdgeInsets.only(bottom: 20);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,92 +79,89 @@ class _AIChatPageState extends State<AIChatPage> {
|
||||
Widget build(BuildContext context) {
|
||||
if (widget.userProfile.authenticator == AuthenticatorPB.AppFlowyCloud) {
|
||||
return buildChatWidget();
|
||||
} else {
|
||||
return Center(
|
||||
child: FlowyText(
|
||||
LocaleKeys.chat_unsupportedCloudPrompt.tr(),
|
||||
fontSize: 20,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Center(
|
||||
child: FlowyText(
|
||||
LocaleKeys.chat_unsupportedCloudPrompt.tr(),
|
||||
fontSize: 20,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildChatWidget() {
|
||||
return SizedBox.expand(
|
||||
child: Padding(
|
||||
padding: AIChatUILayout.chatPadding,
|
||||
child: BlocProvider(
|
||||
create: (context) => ChatBloc(
|
||||
view: widget.view,
|
||||
userProfile: widget.userProfile,
|
||||
)..add(const ChatEvent.initialLoad()),
|
||||
child: BlocBuilder<ChatBloc, ChatState>(
|
||||
builder: (blocContext, state) {
|
||||
return Chat(
|
||||
messages: state.messages,
|
||||
onAttachmentPressed: () {},
|
||||
onSendPressed: (types.PartialText message) {
|
||||
// We use custom bottom widget for chat input, so
|
||||
// do not need to handle this event.
|
||||
},
|
||||
customBottomWidget: buildChatInput(blocContext),
|
||||
user: _user,
|
||||
theme: buildTheme(context),
|
||||
onEndReached: () async {
|
||||
if (state.hasMorePrevMessage &&
|
||||
state.loadingPreviousStatus !=
|
||||
const LoadingState.loading()) {
|
||||
blocContext
|
||||
.read<ChatBloc>()
|
||||
.add(const ChatEvent.startLoadingPrevMessage());
|
||||
}
|
||||
},
|
||||
emptyState: BlocBuilder<ChatBloc, ChatState>(
|
||||
builder: (context, state) {
|
||||
return state.initialLoadingStatus ==
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Flexible(
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 784),
|
||||
child: BlocProvider(
|
||||
create: (_) => ChatBloc(
|
||||
view: widget.view,
|
||||
userProfile: widget.userProfile,
|
||||
)..add(const ChatEvent.initialLoad()),
|
||||
child: BlocBuilder<ChatBloc, ChatState>(
|
||||
builder: (blocContext, state) => Chat(
|
||||
messages: state.messages,
|
||||
onSendPressed: (_) {
|
||||
// We use custom bottom widget for chat input, so
|
||||
// do not need to handle this event.
|
||||
},
|
||||
customBottomWidget: buildChatInput(blocContext),
|
||||
user: _user,
|
||||
theme: buildTheme(context),
|
||||
onEndReached: () async {
|
||||
if (state.hasMorePrevMessage &&
|
||||
state.loadingPreviousStatus !=
|
||||
const LoadingState.loading()) {
|
||||
blocContext
|
||||
.read<ChatBloc>()
|
||||
.add(const ChatEvent.startLoadingPrevMessage());
|
||||
}
|
||||
},
|
||||
emptyState: BlocBuilder<ChatBloc, ChatState>(
|
||||
builder: (_, state) => state.initialLoadingStatus ==
|
||||
const LoadingState.finish()
|
||||
? Padding(
|
||||
padding: AIChatUILayout.welcomePagePadding,
|
||||
child: ChatWelcomePage(
|
||||
onSelectedQuestion: (question) {
|
||||
blocContext
|
||||
.read<ChatBloc>()
|
||||
.add(ChatEvent.sendMessage(question));
|
||||
},
|
||||
onSelectedQuestion: (question) => blocContext
|
||||
.read<ChatBloc>()
|
||||
.add(ChatEvent.sendMessage(question)),
|
||||
),
|
||||
)
|
||||
: const Center(
|
||||
child: CircularProgressIndicator.adaptive(),
|
||||
);
|
||||
),
|
||||
),
|
||||
messageWidthRatio: AIChatUILayout.messageWidthRatio,
|
||||
textMessageBuilder: (
|
||||
textMessage, {
|
||||
required messageWidth,
|
||||
required showName,
|
||||
}) =>
|
||||
_buildAITextMessage(blocContext, textMessage),
|
||||
bubbleBuilder: (
|
||||
child, {
|
||||
required message,
|
||||
required nextMessageInGroup,
|
||||
}) {
|
||||
if (message.author.id == _user.id) {
|
||||
return ChatUserMessageBubble(
|
||||
message: message,
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
|
||||
return _buildAIBubble(message, blocContext, state, child);
|
||||
},
|
||||
),
|
||||
messageWidthRatio: AIChatUILayout.messageWidthRatio,
|
||||
textMessageBuilder: (
|
||||
textMessage, {
|
||||
required messageWidth,
|
||||
required showName,
|
||||
}) {
|
||||
return _buildAITextMessage(blocContext, textMessage);
|
||||
},
|
||||
bubbleBuilder: (
|
||||
child, {
|
||||
required message,
|
||||
required nextMessageInGroup,
|
||||
}) {
|
||||
if (message.author.id == _user.id) {
|
||||
return ChatUserMessageBubble(
|
||||
message: message,
|
||||
child: child,
|
||||
);
|
||||
} else {
|
||||
return _buildAIBubble(message, blocContext, state, child);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'chat_input.dart';
|
||||
|
||||
@@ -31,19 +32,15 @@ class ChatWelcomePage extends StatelessWidget {
|
||||
size: Size.square(44),
|
||||
),
|
||||
const SizedBox(height: 40),
|
||||
GridView.builder(
|
||||
shrinkWrap: true,
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: isMobile ? 2 : 4,
|
||||
crossAxisSpacing: 6,
|
||||
mainAxisSpacing: 6,
|
||||
childAspectRatio: 16.0 / 9.0,
|
||||
),
|
||||
itemCount: items.length,
|
||||
itemBuilder: (context, index) => WelcomeQuestion(
|
||||
question: items[index],
|
||||
onSelected: onSelectedQuestion,
|
||||
),
|
||||
Wrap(
|
||||
children: items
|
||||
.map(
|
||||
(i) => WelcomeQuestion(
|
||||
question: i,
|
||||
onSelected: onSelectedQuestion,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -88,6 +88,7 @@ enum FeatureFlag {
|
||||
|
||||
bool get isOn {
|
||||
if ([
|
||||
FeatureFlag.planBilling,
|
||||
// release this feature in version 0.5.9
|
||||
FeatureFlag.search,
|
||||
// release this feature in version 0.5.6
|
||||
@@ -107,9 +108,9 @@ enum FeatureFlag {
|
||||
switch (this) {
|
||||
case FeatureFlag.collaborativeWorkspace:
|
||||
case FeatureFlag.membersSettings:
|
||||
case FeatureFlag.planBilling:
|
||||
case FeatureFlag.unknown:
|
||||
return false;
|
||||
case FeatureFlag.planBilling:
|
||||
case FeatureFlag.search:
|
||||
case FeatureFlag.syncDocument:
|
||||
case FeatureFlag.syncDatabase:
|
||||
|
||||
@@ -70,7 +70,6 @@ class UserWorkspaceBloc extends Bloc<UserWorkspaceEvent, UserWorkspaceState> {
|
||||
final workspaceMemberResult =
|
||||
await _userService.getWorkspaceMember();
|
||||
final workspaceMember = workspaceMemberResult.toNullable();
|
||||
|
||||
emit(state.copyWith(currentWorkspaceMember: workspaceMember));
|
||||
},
|
||||
fetchWorkspaces: () async {
|
||||
@@ -510,6 +509,7 @@ class UserWorkspaceState with _$UserWorkspaceState {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other is UserWorkspaceState &&
|
||||
other.currentWorkspaceMember == currentWorkspaceMember &&
|
||||
other.currentWorkspace == currentWorkspace &&
|
||||
_deepCollectionEquality.equals(other.workspaces, workspaces) &&
|
||||
identical(other.actionResult, actionResult);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
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/blank/blank.dart';
|
||||
@@ -34,7 +36,6 @@ import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/button.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
/// Home Sidebar is the left side bar of the home page.
|
||||
|
||||
+37
-40
@@ -10,7 +10,6 @@ import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.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_bloc/flutter_bloc.dart';
|
||||
|
||||
class AIFeatureOnlySupportedWhenUsingAppFlowyCloud extends StatelessWidget {
|
||||
@@ -31,30 +30,25 @@ class AIFeatureOnlySupportedWhenUsingAppFlowyCloud extends StatelessWidget {
|
||||
}
|
||||
|
||||
class SettingsAIView extends StatelessWidget {
|
||||
const SettingsAIView({
|
||||
super.key,
|
||||
required this.userProfile,
|
||||
});
|
||||
const SettingsAIView({super.key, required this.userProfile});
|
||||
|
||||
final UserProfilePB userProfile;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider<SettingsAIBloc>(
|
||||
create: (context) =>
|
||||
create: (_) =>
|
||||
SettingsAIBloc(userProfile)..add(const SettingsAIEvent.started()),
|
||||
child: BlocBuilder<SettingsAIBloc, SettingsAIState>(
|
||||
builder: (context, state) {
|
||||
return SettingsBody(
|
||||
title: LocaleKeys.settings_aiPage_title.tr(),
|
||||
description:
|
||||
LocaleKeys.settings_aiPage_keys_aiSettingsDescription.tr(),
|
||||
children: const [
|
||||
AIModelSeclection(),
|
||||
_AISearchToggle(value: false),
|
||||
],
|
||||
);
|
||||
},
|
||||
builder: (_, __) => SettingsBody(
|
||||
title: LocaleKeys.settings_aiPage_title.tr(),
|
||||
description:
|
||||
LocaleKeys.settings_aiPage_keys_aiSettingsDescription.tr(),
|
||||
children: const [
|
||||
AIModelSeclection(),
|
||||
_AISearchToggle(value: false),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -66,23 +60,22 @@ class AIModelSeclection extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
FlowyText(
|
||||
LocaleKeys.settings_aiPage_keys_llmModel.tr(),
|
||||
fontSize: 14,
|
||||
Flexible(
|
||||
child: FlowyText.medium(
|
||||
LocaleKeys.settings_aiPage_keys_llmModel.tr(),
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
BlocBuilder<SettingsAIBloc, SettingsAIState>(
|
||||
builder: (context, state) {
|
||||
return Expanded(
|
||||
child: SettingsDropdown<AIModelPB>(
|
||||
Flexible(
|
||||
child: BlocBuilder<SettingsAIBloc, SettingsAIState>(
|
||||
builder: (context, state) {
|
||||
return SettingsDropdown<AIModelPB>(
|
||||
key: const Key('AIModelDropdown'),
|
||||
expandWidth: false,
|
||||
onChanged: (format) {
|
||||
context.read<SettingsAIBloc>().add(
|
||||
SettingsAIEvent.selectModel(format),
|
||||
);
|
||||
},
|
||||
onChanged: (model) => context
|
||||
.read<SettingsAIBloc>()
|
||||
.add(SettingsAIEvent.selectModel(model)),
|
||||
selectedOption: state.userProfile.aiModel,
|
||||
options: _availableModels
|
||||
.map(
|
||||
@@ -93,9 +86,9 @@ class AIModelSeclection extends StatelessWidget {
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -139,17 +132,21 @@ class _AISearchToggle extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: FlowyText.regular(
|
||||
LocaleKeys.settings_aiPage_keys_enableAISearchTitle.tr(),
|
||||
fontSize: 16,
|
||||
),
|
||||
FlowyText.medium(
|
||||
LocaleKeys.settings_aiPage_keys_enableAISearchTitle.tr(),
|
||||
),
|
||||
const HSpace(16),
|
||||
const Spacer(),
|
||||
BlocBuilder<SettingsAIBloc, SettingsAIState>(
|
||||
builder: (context, state) {
|
||||
if (state.aiSettings == null) {
|
||||
return const CircularProgressIndicator.adaptive();
|
||||
return const Padding(
|
||||
padding: EdgeInsets.only(top: 6),
|
||||
child: SizedBox(
|
||||
height: 26,
|
||||
width: 26,
|
||||
child: CircularProgressIndicator.adaptive(),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Toggle(
|
||||
value: state.enableSearchIndexing,
|
||||
|
||||
+4
-2
@@ -494,6 +494,7 @@ class _ActionButton extends StatelessWidget {
|
||||
? SystemMouseCursors.click
|
||||
: MouseCursor.defer,
|
||||
child: _drawBorder(
|
||||
context,
|
||||
isLM: isLM,
|
||||
isUpgrade: isUpgrade,
|
||||
child: Container(
|
||||
@@ -544,7 +545,8 @@ class _ActionButton extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _drawBorder({
|
||||
Widget _drawBorder(
|
||||
BuildContext context, {
|
||||
required bool isLM,
|
||||
required bool isUpgrade,
|
||||
required Widget child,
|
||||
@@ -562,7 +564,7 @@ class _ActionButton extends StatelessWidget {
|
||||
],
|
||||
)
|
||||
: null,
|
||||
border: isUpgrade ? null : Border.all(),
|
||||
border: isUpgrade ? null : Border.all(color: const Color(0xFF333333)),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
child: child,
|
||||
|
||||
+1
@@ -70,6 +70,7 @@ class SettingsPlanView extends StatelessWidget {
|
||||
usage: state.workspaceUsage,
|
||||
subscription: state.subscription,
|
||||
),
|
||||
const VSpace(16),
|
||||
_CurrentPlanBox(subscription: state.subscription),
|
||||
],
|
||||
),
|
||||
|
||||
+2
-5
@@ -490,14 +490,11 @@ class KeyBadge extends StatelessWidget {
|
||||
),
|
||||
child: Center(
|
||||
child: iconData != null
|
||||
? FlowySvg(
|
||||
iconData!,
|
||||
color: AFThemeExtension.of(context).strongText,
|
||||
)
|
||||
? FlowySvg(iconData!, color: Colors.black)
|
||||
: FlowyText.medium(
|
||||
keyLabel.toLowerCase(),
|
||||
fontSize: 12,
|
||||
color: AFThemeExtension.of(context).strongText,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
+17
-1
@@ -24,6 +24,7 @@ import 'package:appflowy/workspace/presentation/settings/shared/setting_list_til
|
||||
import 'package:appflowy/workspace/presentation/settings/shared/settings_alert_dialog.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/shared/settings_body.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/shared/settings_category.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/shared/settings_category_spacer.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/shared/settings_dashed_divider.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/shared/settings_dropdown.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/shared/settings_input_field.dart';
|
||||
@@ -85,6 +86,7 @@ class SettingsWorkspaceView extends StatelessWidget {
|
||||
return SettingsBody(
|
||||
title: LocaleKeys.settings_workspacePage_title.tr(),
|
||||
description: LocaleKeys.settings_workspacePage_description.tr(),
|
||||
autoSeparate: false,
|
||||
children: [
|
||||
// We don't allow changing workspace name/icon for local/offline
|
||||
if (userProfile.authenticator != AuthenticatorPB.Local) ...[
|
||||
@@ -93,6 +95,7 @@ class SettingsWorkspaceView extends StatelessWidget {
|
||||
.tr(),
|
||||
children: [_WorkspaceNameSetting(member: workspaceMember)],
|
||||
),
|
||||
const SettingsCategorySpacer(),
|
||||
SettingsCategory(
|
||||
title: LocaleKeys.settings_workspacePage_workspaceIcon_title
|
||||
.tr(),
|
||||
@@ -106,11 +109,14 @@ class SettingsWorkspaceView extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
const SettingsCategorySpacer(),
|
||||
],
|
||||
SettingsCategory(
|
||||
title: LocaleKeys.settings_workspacePage_appearance_title.tr(),
|
||||
children: const [AppearanceSelector()],
|
||||
),
|
||||
const VSpace(16),
|
||||
// const SettingsCategorySpacer(),
|
||||
SettingsCategory(
|
||||
title: LocaleKeys.settings_workspacePage_theme_title.tr(),
|
||||
description:
|
||||
@@ -121,6 +127,7 @@ class SettingsWorkspaceView extends StatelessWidget {
|
||||
_DocumentSelectionColorSetting(),
|
||||
],
|
||||
),
|
||||
const SettingsCategorySpacer(),
|
||||
SettingsCategory(
|
||||
title:
|
||||
LocaleKeys.settings_workspacePage_workspaceFont_title.tr(),
|
||||
@@ -129,7 +136,9 @@ class SettingsWorkspaceView extends StatelessWidget {
|
||||
currentFont:
|
||||
context.read<AppearanceSettingsCubit>().state.font,
|
||||
),
|
||||
const SettingsDashedDivider(),
|
||||
SettingsDashedDivider(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
SettingsCategory(
|
||||
title: LocaleKeys.settings_workspacePage_textDirection_title
|
||||
.tr(),
|
||||
@@ -140,11 +149,14 @@ class SettingsWorkspaceView extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
const VSpace(16),
|
||||
SettingsCategory(
|
||||
title: LocaleKeys.settings_workspacePage_layoutDirection_title
|
||||
.tr(),
|
||||
children: const [_LayoutDirectionSelect()],
|
||||
),
|
||||
const SettingsCategorySpacer(),
|
||||
|
||||
SettingsCategory(
|
||||
title: LocaleKeys.settings_workspacePage_dateTime_title.tr(),
|
||||
children: [
|
||||
@@ -156,10 +168,14 @@ class SettingsWorkspaceView extends StatelessWidget {
|
||||
const _DateFormatDropdown(),
|
||||
],
|
||||
),
|
||||
const SettingsCategorySpacer(),
|
||||
|
||||
SettingsCategory(
|
||||
title: LocaleKeys.settings_workspacePage_language_title.tr(),
|
||||
children: const [LanguageDropdown()],
|
||||
),
|
||||
const SettingsCategorySpacer(),
|
||||
|
||||
if (userProfile.authenticator != AuthenticatorPB.Local) ...[
|
||||
SingleSettingAction(
|
||||
label: LocaleKeys.settings_workspacePage_manageWorkspace_title
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/startup/startup.dart';
|
||||
@@ -15,6 +14,7 @@ import 'package:appflowy/workspace/presentation/settings/widgets/feature_flags/f
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/members/workspace_member_page.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_menu.dart';
|
||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_notifications_view.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ class SettingsBody extends StatelessWidget {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
separatorBuilder: () => autoSeparate
|
||||
? const SettingsCategorySpacer()
|
||||
: const VSpace(16),
|
||||
: const SizedBox.shrink(),
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: children,
|
||||
),
|
||||
|
||||
Reference in new issue
Block a user