mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
Merge branch 'main' into feat/support-get-encoded-collab-event
This commit is contained in:
commit
e51b0f90de
11
CHANGELOG.md
11
CHANGELOG.md
@ -1,4 +1,15 @@
|
|||||||
# Release Notes
|
# Release Notes
|
||||||
|
## Version 0.6.2 - 01/07/2024
|
||||||
|
### New Features
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
## Version 0.6.1 - 22/06/2024
|
||||||
|
### New Features
|
||||||
|
- Introduced the "Space" feature to help you organize your pages more efficiently.
|
||||||
|
### Bug Fixes
|
||||||
|
- Resolved shortcut conflicts on the board page.
|
||||||
|
- Resolved an issue where underscores could cause the editor to freeze.
|
||||||
|
|
||||||
## Version 0.6.0 - 19/06/2024
|
## Version 0.6.0 - 19/06/2024
|
||||||
### New Features
|
### New Features
|
||||||
- Introduced the "Space" feature to help you organize your pages more efficiently.
|
- Introduced the "Space" feature to help you organize your pages more efficiently.
|
||||||
|
@ -26,7 +26,7 @@ CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
|
|||||||
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
|
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
|
||||||
CARGO_MAKE_CRATE_NAME = "dart-ffi"
|
CARGO_MAKE_CRATE_NAME = "dart-ffi"
|
||||||
LIB_NAME = "dart_ffi"
|
LIB_NAME = "dart_ffi"
|
||||||
APPFLOWY_VERSION = "0.6.1"
|
APPFLOWY_VERSION = "0.6.2"
|
||||||
FLUTTER_DESKTOP_FEATURES = "dart"
|
FLUTTER_DESKTOP_FEATURES = "dart"
|
||||||
PRODUCT_NAME = "AppFlowy"
|
PRODUCT_NAME = "AppFlowy"
|
||||||
MACOSX_DEPLOYMENT_TARGET = "11.0"
|
MACOSX_DEPLOYMENT_TARGET = "11.0"
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/plugins/ai_chat/chat_page.dart';
|
import 'package:appflowy/plugins/ai_chat/chat_page.dart';
|
||||||
import 'package:appflowy/plugins/util.dart';
|
import 'package:appflowy/plugins/util.dart';
|
||||||
@ -7,7 +9,6 @@ import 'package:appflowy/workspace/presentation/home/home_stack.dart';
|
|||||||
import 'package:appflowy/workspace/presentation/widgets/tab_bar_item.dart';
|
import 'package:appflowy/workspace/presentation/widgets/tab_bar_item.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/view_title_bar.dart';
|
import 'package:appflowy/workspace/presentation/widgets/view_title_bar.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class AIChatPluginBuilder extends PluginBuilder {
|
class AIChatPluginBuilder extends PluginBuilder {
|
||||||
@ -65,6 +66,13 @@ class AIChatPagePlugin extends Plugin {
|
|||||||
_viewInfoBloc = ViewInfoBloc(view: notifier.view)
|
_viewInfoBloc = ViewInfoBloc(view: notifier.view)
|
||||||
..add(const ViewInfoEvent.started());
|
..add(const ViewInfoEvent.started());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_viewInfoBloc.close();
|
||||||
|
notifier.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AIChatPagePluginWidgetBuilder extends PluginWidgetBuilder
|
class AIChatPagePluginWidgetBuilder extends PluginWidgetBuilder
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/plugins/base/emoji/emoji_picker_header.dart';
|
import 'package:appflowy/plugins/base/emoji/emoji_picker_header.dart';
|
||||||
import 'package:appflowy/plugins/base/emoji/emoji_search_bar.dart';
|
import 'package:appflowy/plugins/base/emoji/emoji_search_bar.dart';
|
||||||
import 'package:appflowy/plugins/base/emoji/emoji_skin_tone.dart';
|
import 'package:appflowy/plugins/base/emoji/emoji_skin_tone.dart';
|
||||||
import 'package:flowy_infra/size.dart';
|
import 'package:flowy_infra/size.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_emoji_mart/flutter_emoji_mart.dart';
|
import 'package:flutter_emoji_mart/flutter_emoji_mart.dart';
|
||||||
|
|
||||||
// use a global value to store the selected emoji to prevent reloading every time.
|
// use a global value to store the selected emoji to prevent reloading every time.
|
||||||
@ -37,9 +38,7 @@ class _FlowyEmojiPickerState extends State<FlowyEmojiPicker> {
|
|||||||
EmojiData.builtIn().then(
|
EmojiData.builtIn().then(
|
||||||
(value) {
|
(value) {
|
||||||
kCachedEmojiData = value;
|
kCachedEmojiData = value;
|
||||||
setState(() {
|
setState(() => emojiData = value);
|
||||||
emojiData = value;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/plugins/database/application/field/field_controller.dart';
|
import 'package:appflowy/plugins/database/application/field/field_controller.dart';
|
||||||
import 'package:appflowy/plugins/database/application/view/view_cache.dart';
|
import 'package:appflowy/plugins/database/application/view/view_cache.dart';
|
||||||
import 'package:appflowy/plugins/database/domain/database_view_service.dart';
|
import 'package:appflowy/plugins/database/domain/database_view_service.dart';
|
||||||
@ -12,7 +14,6 @@ import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
|||||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
import 'package:appflowy_result/appflowy_result.dart';
|
import 'package:appflowy_result/appflowy_result.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import 'defines.dart';
|
import 'defines.dart';
|
||||||
import 'row/row_cache.dart';
|
import 'row/row_cache.dart';
|
||||||
@ -223,6 +224,7 @@ class DatabaseController {
|
|||||||
_databaseCallbacks.clear();
|
_databaseCallbacks.clear();
|
||||||
_groupCallbacks.clear();
|
_groupCallbacks.clear();
|
||||||
_layoutCallbacks.clear();
|
_layoutCallbacks.clear();
|
||||||
|
_isLoading.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadGroups() async {
|
Future<void> _loadGroups() async {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
|
||||||
@ -19,12 +21,12 @@ import 'package:flowy_infra/size.dart';
|
|||||||
import 'package:flowy_infra/theme_extension.dart';
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
import '../../application/row/row_controller.dart';
|
import '../../application/row/row_controller.dart';
|
||||||
import '../../widgets/row/row_detail.dart';
|
import '../../widgets/row/row_detail.dart';
|
||||||
|
|
||||||
import 'calendar_day.dart';
|
import 'calendar_day.dart';
|
||||||
import 'layout/sizes.dart';
|
import 'layout/sizes.dart';
|
||||||
import 'toolbar/calendar_setting_bar.dart';
|
import 'toolbar/calendar_setting_bar.dart';
|
||||||
@ -90,12 +92,11 @@ class _CalendarPageState extends State<CalendarPage> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
super.initState();
|
||||||
_calendarState = GlobalKey<MonthViewState>();
|
_calendarState = GlobalKey<MonthViewState>();
|
||||||
_calendarBloc = CalendarBloc(
|
_calendarBloc = CalendarBloc(
|
||||||
databaseController: widget.databaseController,
|
databaseController: widget.databaseController,
|
||||||
)..add(const CalendarEvent.initial());
|
)..add(const CalendarEvent.initial());
|
||||||
|
|
||||||
super.initState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -378,13 +379,7 @@ class UnscheduledEventsButton extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _UnscheduledEventsButtonState extends State<UnscheduledEventsButton> {
|
class _UnscheduledEventsButtonState extends State<UnscheduledEventsButton> {
|
||||||
late final PopoverController _popoverController;
|
final PopoverController _popoverController = PopoverController();
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_popoverController = PopoverController();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -30,6 +30,12 @@ class CalendarLayoutSetting extends StatefulWidget {
|
|||||||
class _CalendarLayoutSettingState extends State<CalendarLayoutSetting> {
|
class _CalendarLayoutSettingState extends State<CalendarLayoutSetting> {
|
||||||
final PopoverMutex popoverMutex = PopoverMutex();
|
final PopoverMutex popoverMutex = PopoverMutex();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
popoverMutex.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/database/grid/application/filter/checkbox_filter_editor_bloc.dart';
|
import 'package:appflowy/plugins/database/grid/application/filter/checkbox_filter_editor_bloc.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
||||||
|
import 'package:appflowy_backend/protobuf/flowy-database2/checkbox_filter.pbenum.dart';
|
||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-database2/checkbox_filter.pbenum.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import '../condition_button.dart';
|
import '../condition_button.dart';
|
||||||
import '../disclosure_button.dart';
|
import '../disclosure_button.dart';
|
||||||
import '../filter_info.dart';
|
import '../filter_info.dart';
|
||||||
|
|
||||||
import 'choicechip.dart';
|
import 'choicechip.dart';
|
||||||
|
|
||||||
class CheckboxFilterChoicechip extends StatefulWidget {
|
class CheckboxFilterChoicechip extends StatefulWidget {
|
||||||
@ -30,9 +31,9 @@ class _CheckboxFilterChoicechipState extends State<CheckboxFilterChoicechip> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
super.initState();
|
||||||
bloc = CheckboxFilterEditorBloc(filterInfo: widget.filterInfo)
|
bloc = CheckboxFilterEditorBloc(filterInfo: widget.filterInfo)
|
||||||
..add(const CheckboxFilterEditorEvent.initial());
|
..add(const CheckboxFilterEditorEvent.initial());
|
||||||
super.initState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -82,6 +83,12 @@ class CheckboxFilterEditor extends StatefulWidget {
|
|||||||
class _CheckboxFilterEditorState extends State<CheckboxFilterEditor> {
|
class _CheckboxFilterEditorState extends State<CheckboxFilterEditor> {
|
||||||
final popoverMutex = PopoverMutex();
|
final popoverMutex = PopoverMutex();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
popoverMutex.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider.value(
|
return BlocProvider.value(
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/database/grid/application/filter/checklist_filter_bloc.dart';
|
import 'package:appflowy/plugins/database/grid/application/filter/checklist_filter_bloc.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
||||||
|
import 'package:appflowy_backend/protobuf/flowy-database2/checklist_filter.pbenum.dart';
|
||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-database2/checklist_filter.pbenum.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import '../../condition_button.dart';
|
import '../../condition_button.dart';
|
||||||
import '../../disclosure_button.dart';
|
import '../../disclosure_button.dart';
|
||||||
import '../../filter_info.dart';
|
import '../../filter_info.dart';
|
||||||
@ -23,20 +25,20 @@ class ChecklistFilterChoicechip extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ChecklistFilterChoicechipState extends State<ChecklistFilterChoicechip> {
|
class _ChecklistFilterChoicechipState extends State<ChecklistFilterChoicechip> {
|
||||||
late ChecklistFilterEditorBloc bloc;
|
late final ChecklistFilterEditorBloc bloc;
|
||||||
late PopoverMutex popoverMutex;
|
final PopoverMutex popoverMutex = PopoverMutex();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
popoverMutex = PopoverMutex();
|
super.initState();
|
||||||
bloc = ChecklistFilterEditorBloc(filterInfo: widget.filterInfo);
|
bloc = ChecklistFilterEditorBloc(filterInfo: widget.filterInfo);
|
||||||
bloc.add(const ChecklistFilterEditorEvent.initial());
|
bloc.add(const ChecklistFilterEditorEvent.initial());
|
||||||
super.initState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
bloc.close();
|
bloc.close();
|
||||||
|
popoverMutex.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/database/grid/application/filter/number_filter_editor_bloc.dart';
|
import 'package:appflowy/plugins/database/grid/application/filter/number_filter_editor_bloc.dart';
|
||||||
@ -6,12 +8,12 @@ import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
|||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import '../condition_button.dart';
|
import '../condition_button.dart';
|
||||||
import '../disclosure_button.dart';
|
import '../disclosure_button.dart';
|
||||||
import '../filter_info.dart';
|
import '../filter_info.dart';
|
||||||
|
|
||||||
import 'choicechip.dart';
|
import 'choicechip.dart';
|
||||||
|
|
||||||
class NumberFilterChoiceChip extends StatefulWidget {
|
class NumberFilterChoiceChip extends StatefulWidget {
|
||||||
@ -64,6 +66,12 @@ class NumberFilterEditor extends StatefulWidget {
|
|||||||
class _NumberFilterEditorState extends State<NumberFilterEditor> {
|
class _NumberFilterEditorState extends State<NumberFilterEditor> {
|
||||||
final popoverMutex = PopoverMutex();
|
final popoverMutex = PopoverMutex();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
popoverMutex.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<NumberFilterEditorBloc, NumberFilterEditorState>(
|
return BlocBuilder<NumberFilterEditorBloc, NumberFilterEditorState>(
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/plugins/database/grid/application/filter/select_option_filter_bloc.dart';
|
import 'package:appflowy/plugins/database/grid/application/filter/select_option_filter_bloc.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-database2/select_option_filter.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-database2/select_option_filter.pb.dart';
|
||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import '../../disclosure_button.dart';
|
import '../../disclosure_button.dart';
|
||||||
import '../../filter_info.dart';
|
import '../../filter_info.dart';
|
||||||
import '../choicechip.dart';
|
import '../choicechip.dart';
|
||||||
|
|
||||||
import 'condition_list.dart';
|
import 'condition_list.dart';
|
||||||
import 'option_list.dart';
|
import 'option_list.dart';
|
||||||
import 'select_option_loader.dart';
|
import 'select_option_loader.dart';
|
||||||
@ -29,6 +31,7 @@ class _SelectOptionFilterChoicechipState
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
super.initState();
|
||||||
if (widget.filterInfo.fieldInfo.fieldType == FieldType.SingleSelect) {
|
if (widget.filterInfo.fieldInfo.fieldType == FieldType.SingleSelect) {
|
||||||
bloc = SelectOptionFilterEditorBloc(
|
bloc = SelectOptionFilterEditorBloc(
|
||||||
filterInfo: widget.filterInfo,
|
filterInfo: widget.filterInfo,
|
||||||
@ -43,7 +46,6 @@ class _SelectOptionFilterChoicechipState
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
bloc.add(const SelectOptionFilterEditorEvent.initial());
|
bloc.add(const SelectOptionFilterEditorEvent.initial());
|
||||||
super.initState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -90,6 +92,12 @@ class SelectOptionFilterEditor extends StatefulWidget {
|
|||||||
class _SelectOptionFilterEditorState extends State<SelectOptionFilterEditor> {
|
class _SelectOptionFilterEditorState extends State<SelectOptionFilterEditor> {
|
||||||
final popoverMutex = PopoverMutex();
|
final popoverMutex = PopoverMutex();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
popoverMutex.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider.value(
|
return BlocProvider.value(
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/database/grid/application/filter/text_filter_editor_bloc.dart';
|
import 'package:appflowy/plugins/database/grid/application/filter/text_filter_editor_bloc.dart';
|
||||||
@ -6,12 +8,12 @@ import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
|||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import '../condition_button.dart';
|
import '../condition_button.dart';
|
||||||
import '../disclosure_button.dart';
|
import '../disclosure_button.dart';
|
||||||
import '../filter_info.dart';
|
import '../filter_info.dart';
|
||||||
|
|
||||||
import 'choicechip.dart';
|
import 'choicechip.dart';
|
||||||
|
|
||||||
class TextFilterChoicechip extends StatelessWidget {
|
class TextFilterChoicechip extends StatelessWidget {
|
||||||
@ -72,6 +74,12 @@ class TextFilterEditor extends StatefulWidget {
|
|||||||
class _TextFilterEditorState extends State<TextFilterEditor> {
|
class _TextFilterEditorState extends State<TextFilterEditor> {
|
||||||
final popoverMutex = PopoverMutex();
|
final popoverMutex = PopoverMutex();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
popoverMutex.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<TextFilterEditorBloc, TextFilterEditorState>(
|
return BlocBuilder<TextFilterEditorBloc, TextFilterEditorState>(
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/database/grid/application/filter/time_filter_editor_bloc.dart';
|
import 'package:appflowy/plugins/database/grid/application/filter/time_filter_editor_bloc.dart';
|
||||||
@ -6,12 +8,12 @@ import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
|||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import '../condition_button.dart';
|
import '../condition_button.dart';
|
||||||
import '../disclosure_button.dart';
|
import '../disclosure_button.dart';
|
||||||
import '../filter_info.dart';
|
import '../filter_info.dart';
|
||||||
|
|
||||||
import 'choicechip.dart';
|
import 'choicechip.dart';
|
||||||
|
|
||||||
class TimeFilterChoiceChip extends StatefulWidget {
|
class TimeFilterChoiceChip extends StatefulWidget {
|
||||||
@ -64,6 +66,12 @@ class TimeFilterEditor extends StatefulWidget {
|
|||||||
class _TimeFilterEditorState extends State<TimeFilterEditor> {
|
class _TimeFilterEditorState extends State<TimeFilterEditor> {
|
||||||
final popoverMutex = PopoverMutex();
|
final popoverMutex = PopoverMutex();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
popoverMutex.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<TimeFilterEditorBloc, TimeFilterEditorState>(
|
return BlocBuilder<TimeFilterEditorBloc, TimeFilterEditorState>(
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/database/application/field/field_info.dart';
|
import 'package:appflowy/plugins/database/application/field/field_info.dart';
|
||||||
@ -10,7 +12,6 @@ import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
|
|||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text_field.dart';
|
import 'package:flowy_infra_ui/style_widget/text_field.dart';
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import '../../../../application/field/field_controller.dart';
|
import '../../../../application/field/field_controller.dart';
|
||||||
@ -35,15 +36,15 @@ class GridCreateFilterList extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _GridCreateFilterListState extends State<GridCreateFilterList> {
|
class _GridCreateFilterListState extends State<GridCreateFilterList> {
|
||||||
late GridCreateFilterBloc editBloc;
|
late final GridCreateFilterBloc editBloc;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
super.initState();
|
||||||
editBloc = GridCreateFilterBloc(
|
editBloc = GridCreateFilterBloc(
|
||||||
viewId: widget.viewId,
|
viewId: widget.viewId,
|
||||||
fieldController: widget.fieldController,
|
fieldController: widget.fieldController,
|
||||||
)..add(const GridCreateFilterEvent.initial());
|
)..add(const GridCreateFilterEvent.initial());
|
||||||
super.initState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/database/application/field/field_controller.dart';
|
import 'package:appflowy/plugins/database/application/field/field_controller.dart';
|
||||||
@ -5,9 +7,7 @@ import 'package:appflowy/plugins/database/grid/application/filter/filter_menu_bl
|
|||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra/theme_extension.dart';
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
|
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import 'create_filter_list.dart';
|
import 'create_filter_list.dart';
|
||||||
@ -77,13 +77,7 @@ class AddFilterButton extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _AddFilterButtonState extends State<AddFilterButton> {
|
class _AddFilterButtonState extends State<AddFilterButton> {
|
||||||
late PopoverController popoverController;
|
final PopoverController popoverController = PopoverController();
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
popoverController = PopoverController();
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/plugins/database/application/field/field_cell_bloc.dart';
|
import 'package:appflowy/plugins/database/application/field/field_cell_bloc.dart';
|
||||||
import 'package:appflowy/plugins/database/application/field/field_controller.dart';
|
import 'package:appflowy/plugins/database/application/field/field_controller.dart';
|
||||||
@ -9,7 +11,6 @@ import 'package:appflowy_popover/appflowy_popover.dart';
|
|||||||
import 'package:flowy_infra/theme_extension.dart';
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import '../../layout/sizes.dart';
|
import '../../layout/sizes.dart';
|
||||||
@ -41,13 +42,12 @@ class GridFieldCell extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _GridFieldCellState extends State<GridFieldCell> {
|
class _GridFieldCellState extends State<GridFieldCell> {
|
||||||
|
final PopoverController popoverController = PopoverController();
|
||||||
late final FieldCellBloc _bloc;
|
late final FieldCellBloc _bloc;
|
||||||
late PopoverController popoverController;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
popoverController = PopoverController();
|
|
||||||
_bloc = FieldCellBloc(viewId: widget.viewId, fieldInfo: widget.fieldInfo);
|
_bloc = FieldCellBloc(viewId: widget.viewId, fieldInfo: widget.fieldInfo);
|
||||||
if (widget.isEditing) {
|
if (widget.isEditing) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/database/grid/application/sort/sort_editor_bloc.dart';
|
import 'package:appflowy/plugins/database/grid/application/sort/sort_editor_bloc.dart';
|
||||||
@ -7,10 +9,8 @@ import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
|||||||
import 'package:appflowy_backend/protobuf/flowy-database2/sort_entities.pbenum.dart';
|
import 'package:appflowy_backend/protobuf/flowy-database2/sort_entities.pbenum.dart';
|
||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
|
||||||
import 'package:flowy_infra/theme_extension.dart';
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import 'create_sort_list.dart';
|
import 'create_sort_list.dart';
|
||||||
@ -28,6 +28,12 @@ class SortEditor extends StatefulWidget {
|
|||||||
class _SortEditorState extends State<SortEditor> {
|
class _SortEditorState extends State<SortEditor> {
|
||||||
final popoverMutex = PopoverMutex();
|
final popoverMutex = PopoverMutex();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
popoverMutex.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<SortEditorBloc, SortEditorState>(
|
return BlocBuilder<SortEditorBloc, SortEditorState>(
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/database/application/cell/bloc/select_option_cell_editor_bloc.dart';
|
import 'package:appflowy/plugins/database/application/cell/bloc/select_option_cell_editor_bloc.dart';
|
||||||
@ -10,14 +14,12 @@ import 'package:appflowy_popover/appflowy_popover.dart';
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra/theme_extension.dart';
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import '../../grid/presentation/layout/sizes.dart';
|
import '../../grid/presentation/layout/sizes.dart';
|
||||||
import '../../grid/presentation/widgets/common/type_option_separator.dart';
|
import '../../grid/presentation/widgets/common/type_option_separator.dart';
|
||||||
import '../field/type_option_editor/select/select_option_editor.dart';
|
import '../field/type_option_editor/select/select_option_editor.dart';
|
||||||
|
|
||||||
import 'extension.dart';
|
import 'extension.dart';
|
||||||
import 'select_option_text_field.dart';
|
import 'select_option_text_field.dart';
|
||||||
|
|
||||||
@ -314,13 +316,7 @@ class _SelectOptionCell extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _SelectOptionCellState extends State<_SelectOptionCell> {
|
class _SelectOptionCellState extends State<_SelectOptionCell> {
|
||||||
late PopoverController _popoverController;
|
final _popoverController = PopoverController();
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
_popoverController = PopoverController();
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -370,13 +370,7 @@ class FieldDetailsEditor extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _FieldDetailsEditorState extends State<FieldDetailsEditor> {
|
class _FieldDetailsEditorState extends State<FieldDetailsEditor> {
|
||||||
late PopoverMutex popoverMutex;
|
final PopoverMutex popoverMutex = PopoverMutex();
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
popoverMutex = PopoverMutex();
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
@ -575,10 +569,7 @@ class _FieldNameTextFieldState extends State<FieldNameTextField> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class SwitchFieldButton extends StatefulWidget {
|
class SwitchFieldButton extends StatefulWidget {
|
||||||
const SwitchFieldButton({
|
const SwitchFieldButton({super.key, required this.popoverMutex});
|
||||||
super.key,
|
|
||||||
required this.popoverMutex,
|
|
||||||
});
|
|
||||||
|
|
||||||
final PopoverMutex popoverMutex;
|
final PopoverMutex popoverMutex;
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/database/application/cell/cell_controller.dart';
|
import 'package:appflowy/plugins/database/application/cell/cell_controller.dart';
|
||||||
@ -18,13 +21,12 @@ import 'package:collection/collection.dart';
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra/theme_extension.dart';
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import 'accessory/cell_accessory.dart';
|
|
||||||
import '../cell/editable_cell_builder.dart';
|
import '../cell/editable_cell_builder.dart';
|
||||||
|
|
||||||
|
import 'accessory/cell_accessory.dart';
|
||||||
|
|
||||||
/// Display the row properties in a list. Only used in [RowDetailPage].
|
/// Display the row properties in a list. Only used in [RowDetailPage].
|
||||||
class RowPropertyList extends StatelessWidget {
|
class RowPropertyList extends StatelessWidget {
|
||||||
const RowPropertyList({
|
const RowPropertyList({
|
||||||
@ -363,15 +365,9 @@ class CreateRowFieldButton extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _CreateRowFieldButtonState extends State<CreateRowFieldButton> {
|
class _CreateRowFieldButtonState extends State<CreateRowFieldButton> {
|
||||||
late PopoverController popoverController;
|
final PopoverController popoverController = PopoverController();
|
||||||
FieldPB? createdField;
|
FieldPB? createdField;
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
popoverController = PopoverController();
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AppFlowyPopover(
|
return AppFlowyPopover(
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
import 'package:appflowy/plugins/database/application/database_controller.dart';
|
import 'package:appflowy/plugins/database/application/database_controller.dart';
|
||||||
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
||||||
import 'package:appflowy/plugins/database/widgets/setting/database_setting_action.dart';
|
import 'package:appflowy/plugins/database/widgets/setting/database_setting_action.dart';
|
||||||
@ -6,7 +8,6 @@ import 'package:appflowy_editor/appflowy_editor.dart';
|
|||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
|
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
|
|
||||||
class DatabaseSettingsList extends StatefulWidget {
|
class DatabaseSettingsList extends StatefulWidget {
|
||||||
const DatabaseSettingsList({
|
const DatabaseSettingsList({
|
||||||
@ -21,7 +22,13 @@ class DatabaseSettingsList extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _DatabaseSettingsListState extends State<DatabaseSettingsList> {
|
class _DatabaseSettingsListState extends State<DatabaseSettingsList> {
|
||||||
late final PopoverMutex popoverMutex = PopoverMutex();
|
final PopoverMutex popoverMutex = PopoverMutex();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
popoverMutex.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/plugins/database/application/field/field_controller.dart';
|
import 'package:appflowy/plugins/database/application/field/field_controller.dart';
|
||||||
import 'package:appflowy/plugins/database/application/field/field_info.dart';
|
import 'package:appflowy/plugins/database/application/field/field_info.dart';
|
||||||
@ -13,7 +15,6 @@ import 'package:appflowy_popover/appflowy_popover.dart';
|
|||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flowy_infra/theme_extension.dart';
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class DatabasePropertyList extends StatefulWidget {
|
class DatabasePropertyList extends StatefulWidget {
|
||||||
@ -43,6 +44,12 @@ class _DatabasePropertyListState extends State<DatabasePropertyList> {
|
|||||||
)..add(const DatabasePropertyEvent.initial());
|
)..add(const DatabasePropertyEvent.initial());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_popoverMutex.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider<DatabasePropertyBloc>.value(
|
return BlocProvider<DatabasePropertyBloc>.value(
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
|
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
|
||||||
@ -25,7 +27,6 @@ import 'package:collection/collection.dart';
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:fixnum/fixnum.dart';
|
import 'package:fixnum/fixnum.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:nanoid/non_secure.dart';
|
import 'package:nanoid/non_secure.dart';
|
||||||
|
|
||||||
@ -64,6 +65,12 @@ class _MentionDateBlockState extends State<MentionDateBlock> {
|
|||||||
late bool _includeTime = widget.includeTime;
|
late bool _includeTime = widget.includeTime;
|
||||||
late DateTime? parsedDate = DateTime.tryParse(widget.date);
|
late DateTime? parsedDate = DateTime.tryParse(widget.date);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
mutex.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (parsedDate == null) {
|
if (parsedDate == null) {
|
||||||
|
@ -85,12 +85,32 @@ class InitAppWindowTask extends LaunchTask with WindowListener {
|
|||||||
Future<void> onWindowMaximize() async {
|
Future<void> onWindowMaximize() async {
|
||||||
super.onWindowMaximize();
|
super.onWindowMaximize();
|
||||||
await windowSizeManager.setWindowMaximized(true);
|
await windowSizeManager.setWindowMaximized(true);
|
||||||
|
await windowSizeManager.setPosition(Offset.zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> onWindowUnmaximize() async {
|
Future<void> onWindowUnmaximize() async {
|
||||||
super.onWindowUnmaximize();
|
super.onWindowUnmaximize();
|
||||||
await windowSizeManager.setWindowMaximized(false);
|
await windowSizeManager.setWindowMaximized(false);
|
||||||
|
|
||||||
|
final position = await windowManager.getPosition();
|
||||||
|
return windowSizeManager.setPosition(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onWindowEnterFullScreen() async {
|
||||||
|
super.onWindowEnterFullScreen();
|
||||||
|
await windowSizeManager.setWindowMaximized(true);
|
||||||
|
await windowSizeManager.setPosition(Offset.zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> onWindowLeaveFullScreen() async {
|
||||||
|
super.onWindowLeaveFullScreen();
|
||||||
|
await windowSizeManager.setWindowMaximized(false);
|
||||||
|
|
||||||
|
final position = await windowManager.getPosition();
|
||||||
|
return windowSizeManager.setPosition(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -109,7 +109,7 @@ class UserBackendService implements IUserBackendService {
|
|||||||
return UserEventOpenWorkspace(payload).send();
|
return UserEventOpenWorkspace(payload).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<FlowyResult<WorkspacePB, FlowyError>> getCurrentWorkspace() {
|
static Future<FlowyResult<WorkspacePB, FlowyError>> getCurrentWorkspace() {
|
||||||
return FolderEventReadCurrentWorkspace().send().then((result) {
|
return FolderEventReadCurrentWorkspace().send().then((result) {
|
||||||
return result.fold(
|
return result.fold(
|
||||||
(workspace) => FlowyResult.success(workspace),
|
(workspace) => FlowyResult.success(workspace),
|
||||||
|
@ -67,8 +67,9 @@ class SettingsAIBloc extends Bloc<SettingsAIEvent, SettingsAIState> {
|
|||||||
bool? disableSearchIndexing,
|
bool? disableSearchIndexing,
|
||||||
AIModelPB? model,
|
AIModelPB? model,
|
||||||
}) {
|
}) {
|
||||||
final payload =
|
final payload = UpdateUserWorkspaceSettingPB(
|
||||||
UpdateUserWorkspaceSettingPB(workspaceId: userProfile.workspaceId);
|
workspaceId: userProfile.workspaceId,
|
||||||
|
);
|
||||||
if (disableSearchIndexing != null) {
|
if (disableSearchIndexing != null) {
|
||||||
payload.disableSearchIndexing = disableSearchIndexing;
|
payload.disableSearchIndexing = disableSearchIndexing;
|
||||||
}
|
}
|
||||||
@ -82,17 +83,16 @@ class SettingsAIBloc extends Bloc<SettingsAIEvent, SettingsAIState> {
|
|||||||
FlowyResult<UserProfilePB, FlowyError> userProfileOrFailed,
|
FlowyResult<UserProfilePB, FlowyError> userProfileOrFailed,
|
||||||
) =>
|
) =>
|
||||||
userProfileOrFailed.fold(
|
userProfileOrFailed.fold(
|
||||||
(newUserProfile) =>
|
(profile) => add(SettingsAIEvent.didReceiveUserProfile(profile)),
|
||||||
add(SettingsAIEvent.didReceiveUserProfile(newUserProfile)),
|
|
||||||
(err) => Log.error(err),
|
(err) => Log.error(err),
|
||||||
);
|
);
|
||||||
|
|
||||||
void _loadUserWorkspaceSetting() {
|
void _loadUserWorkspaceSetting() {
|
||||||
final payload = UserWorkspaceIdPB(workspaceId: userProfile.workspaceId);
|
final payload = UserWorkspaceIdPB(workspaceId: userProfile.workspaceId);
|
||||||
UserEventGetWorkspaceSetting(payload).send().then((result) {
|
UserEventGetWorkspaceSetting(payload).send().then((result) {
|
||||||
result.fold((settins) {
|
result.fold((settings) {
|
||||||
if (!isClosed) {
|
if (!isClosed) {
|
||||||
add(SettingsAIEvent.didLoadAISetting(settins));
|
add(SettingsAIEvent.didLoadAISetting(settings));
|
||||||
}
|
}
|
||||||
}, (err) {
|
}, (err) {
|
||||||
Log.error(err);
|
Log.error(err);
|
||||||
|
@ -117,6 +117,10 @@ class SettingsPlanBloc extends Bloc<SettingsPlanEvent, SettingsPlanState> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
cancelSubscription: () async {
|
cancelSubscription: () async {
|
||||||
|
final newState = state
|
||||||
|
.mapOrNull(ready: (state) => state)
|
||||||
|
?.copyWith(downgradeProcessing: true);
|
||||||
|
emit(newState ?? state);
|
||||||
await _userService.cancelSubscription(workspaceId);
|
await _userService.cancelSubscription(workspaceId);
|
||||||
add(const SettingsPlanEvent.started());
|
add(const SettingsPlanEvent.started());
|
||||||
},
|
},
|
||||||
@ -174,5 +178,6 @@ class SettingsPlanState with _$SettingsPlanState {
|
|||||||
required WorkspaceSubscriptionPB subscription,
|
required WorkspaceSubscriptionPB subscription,
|
||||||
required BillingPortalPB? billingPortal,
|
required BillingPortalPB? billingPortal,
|
||||||
@Default(false) bool showSuccessDialog,
|
@Default(false) bool showSuccessDialog,
|
||||||
|
@Default(false) bool downgradeProcessing,
|
||||||
}) = _Ready;
|
}) = _Ready;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,20 @@
|
|||||||
import 'package:appflowy_backend/protobuf/flowy-user/workspace.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-user/workspace.pb.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
final _storageNumberFormat = NumberFormat()
|
||||||
|
..maximumFractionDigits = 2
|
||||||
|
..minimumFractionDigits = 0;
|
||||||
|
|
||||||
extension PresentableUsage on WorkspaceUsagePB {
|
extension PresentableUsage on WorkspaceUsagePB {
|
||||||
String get totalBlobInGb =>
|
String get totalBlobInGb =>
|
||||||
(totalBlobBytesLimit.toInt() / 1024 / 1024 / 1024).round().toString();
|
(totalBlobBytesLimit.toInt() / 1024 / 1024 / 1024).round().toString();
|
||||||
|
|
||||||
|
/// We use [NumberFormat] to format the current blob in GB.
|
||||||
|
///
|
||||||
|
/// Where the [totalBlobBytes] is the total blob bytes in bytes.
|
||||||
|
/// And [NumberFormat.maximumFractionDigits] is set to 2.
|
||||||
|
/// And [NumberFormat.minimumFractionDigits] is set to 0.
|
||||||
|
///
|
||||||
String get currentBlobInGb =>
|
String get currentBlobInGb =>
|
||||||
(totalBlobBytes.toInt() / 1024 / 1024 / 1024).round().toString();
|
_storageNumberFormat.format(totalBlobBytes.toInt() / 1024 / 1024 / 1024);
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ class WorkspaceSettingsBloc
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
final currentWorkspace =
|
final currentWorkspace =
|
||||||
await _userService!.getCurrentWorkspace().getOrThrow();
|
await UserBackendService.getCurrentWorkspace().getOrThrow();
|
||||||
|
|
||||||
final workspaces =
|
final workspaces =
|
||||||
await _userService!.getWorkspaces().getOrThrow();
|
await _userService!.getWorkspaces().getOrThrow();
|
||||||
|
@ -297,12 +297,11 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
|
|||||||
if (currentSpace == null) {
|
if (currentSpace == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await ViewBackendService.duplicate(
|
final newSpace = await _duplicateSpace(currentSpace);
|
||||||
view: currentSpace,
|
// open the duplicated space
|
||||||
openAfterDuplicate: false,
|
if (newSpace != null) {
|
||||||
includeChildren: true,
|
add(SpaceEvent.open(newSpace));
|
||||||
);
|
}
|
||||||
add(const SpaceEvent.didReceiveSpaceUpdate());
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -602,6 +601,40 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<ViewPB?> _duplicateSpace(ViewPB space) async {
|
||||||
|
// if the space is not duplicated, try to create a new space
|
||||||
|
final icon = space.icon.value.isNotEmpty
|
||||||
|
? space.icon.value
|
||||||
|
: builtInSpaceIcons.first;
|
||||||
|
final iconColor = space.spaceIconColor ?? builtInSpaceColors.first;
|
||||||
|
final newSpace = await _createSpace(
|
||||||
|
name: '${space.name} (copy)',
|
||||||
|
icon: icon,
|
||||||
|
iconColor: iconColor,
|
||||||
|
permission: space.spacePermission,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (newSpace == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final view in space.childViews) {
|
||||||
|
unawaited(
|
||||||
|
ViewBackendService.duplicate(
|
||||||
|
view: view,
|
||||||
|
openAfterDuplicate: true,
|
||||||
|
includeChildren: true,
|
||||||
|
parentViewId: newSpace.id,
|
||||||
|
suffix: '',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.info('Space duplicated: $newSpace');
|
||||||
|
add(const SpaceEvent.didReceiveSpaceUpdate());
|
||||||
|
return newSpace;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import 'package:flutter/foundation.dart';
|
|
||||||
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/shared/feature_flags.dart';
|
import 'package:appflowy/shared/feature_flags.dart';
|
||||||
import 'package:appflowy/user/application/user_listener.dart';
|
import 'package:appflowy/user/application/user_listener.dart';
|
||||||
@ -12,6 +10,7 @@ import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
|||||||
import 'package:appflowy_result/appflowy_result.dart';
|
import 'package:appflowy_result/appflowy_result.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'package:protobuf/protobuf.dart';
|
import 'package:protobuf/protobuf.dart';
|
||||||
@ -406,7 +405,7 @@ class UserWorkspaceBloc extends Bloc<UserWorkspaceEvent, UserWorkspaceState> {
|
|||||||
)> _fetchWorkspaces() async {
|
)> _fetchWorkspaces() async {
|
||||||
try {
|
try {
|
||||||
final currentWorkspace =
|
final currentWorkspace =
|
||||||
await _userService.getCurrentWorkspace().getOrThrow();
|
await UserBackendService.getCurrentWorkspace().getOrThrow();
|
||||||
final workspaces = await _userService.getWorkspaces().getOrThrow();
|
final workspaces = await _userService.getWorkspaces().getOrThrow();
|
||||||
if (workspaces.isEmpty) {
|
if (workspaces.isEmpty) {
|
||||||
workspaces.add(convertWorkspacePBToUserWorkspace(currentWorkspace));
|
workspaces.add(convertWorkspacePBToUserWorkspace(currentWorkspace));
|
||||||
|
@ -141,11 +141,22 @@ class ViewBackendService {
|
|||||||
required bool openAfterDuplicate,
|
required bool openAfterDuplicate,
|
||||||
// should include children views
|
// should include children views
|
||||||
required bool includeChildren,
|
required bool includeChildren,
|
||||||
|
String? parentViewId,
|
||||||
|
String? suffix,
|
||||||
}) {
|
}) {
|
||||||
final payload = DuplicateViewPayloadPB.create()
|
final payload = DuplicateViewPayloadPB.create()
|
||||||
..viewId = view.id
|
..viewId = view.id
|
||||||
..openAfterDuplicate = openAfterDuplicate
|
..openAfterDuplicate = openAfterDuplicate
|
||||||
..includeChildren = includeChildren;
|
..includeChildren = includeChildren;
|
||||||
|
|
||||||
|
if (parentViewId != null) {
|
||||||
|
payload.parentViewId = parentViewId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (suffix != null) {
|
||||||
|
payload.suffix = suffix;
|
||||||
|
}
|
||||||
|
|
||||||
return FolderEventDuplicateView(payload).send();
|
return FolderEventDuplicateView(payload).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:appflowy/startup/tasks/app_window_size_manager.dart';
|
import 'package:appflowy/startup/tasks/app_window_size_manager.dart';
|
||||||
import 'package:appflowy/workspace/application/home/home_setting_bloc.dart';
|
import 'package:appflowy/workspace/application/home/home_setting_bloc.dart';
|
||||||
@ -9,7 +11,6 @@ import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
|
|||||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/shared/sidebar_setting.dart';
|
import 'package:appflowy/workspace/presentation/home/menu/sidebar/shared/sidebar_setting.dart';
|
||||||
import 'package:appflowy_backend/log.dart';
|
import 'package:appflowy_backend/log.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:hotkey_manager/hotkey_manager.dart';
|
import 'package:hotkey_manager/hotkey_manager.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:scaled_app/scaled_app.dart';
|
import 'package:scaled_app/scaled_app.dart';
|
||||||
@ -186,14 +187,12 @@ class _HomeHotKeysState extends State<HomeHotKeys> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
_registerHotKeys(context);
|
_registerHotKeys(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
|
|
||||||
_registerHotKeys(context);
|
_registerHotKeys(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
|
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/home_sizes.dart';
|
import 'package:appflowy/workspace/presentation/home/home_sizes.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/tabs/flowy_tab.dart';
|
import 'package:appflowy/workspace/presentation/home/tabs/flowy_tab.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class TabsManager extends StatefulWidget {
|
class TabsManager extends StatefulWidget {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:appflowy/user/application/notification_filter/notification_filter_bloc.dart';
|
import 'package:appflowy/user/application/notification_filter/notification_filter_bloc.dart';
|
||||||
import 'package:appflowy/user/application/reminder/reminder_bloc.dart';
|
import 'package:appflowy/user/application/reminder/reminder_bloc.dart';
|
||||||
@ -9,7 +11,6 @@ import 'package:appflowy/workspace/presentation/notifications/widgets/notificati
|
|||||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-user/reminder.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-user/reminder.pb.dart';
|
||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class NotificationDialog extends StatefulWidget {
|
class NotificationDialog extends StatefulWidget {
|
||||||
@ -44,7 +45,7 @@ class _NotificationDialogState extends State<NotificationDialog>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_mutex.close();
|
_mutex.dispose();
|
||||||
_controller.removeListener(_updateState);
|
_controller.removeListener(_updateState);
|
||||||
_controller.dispose();
|
_controller.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
@ -10,18 +12,27 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flowy_infra/theme_extension.dart';
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class NotificationButton extends StatelessWidget {
|
class NotificationButton extends StatefulWidget {
|
||||||
const NotificationButton({
|
const NotificationButton({super.key});
|
||||||
super.key,
|
|
||||||
});
|
@override
|
||||||
|
State<NotificationButton> createState() => _NotificationButtonState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _NotificationButtonState extends State<NotificationButton> {
|
||||||
|
final mutex = PopoverMutex();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
mutex.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final views = context.watch<SidebarSectionsBloc>().state.section.views;
|
final views = context.watch<SidebarSectionsBloc>().state.section.views;
|
||||||
final mutex = PopoverMutex();
|
|
||||||
|
|
||||||
return BlocProvider<ReminderBloc>.value(
|
return BlocProvider<ReminderBloc>.value(
|
||||||
value: getIt<ReminderBloc>(),
|
value: getIt<ReminderBloc>(),
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_configuration.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_configuration.dart';
|
||||||
@ -12,7 +14,6 @@ import 'package:fixnum/fixnum.dart';
|
|||||||
import 'package:flowy_infra/size.dart';
|
import 'package:flowy_infra/size.dart';
|
||||||
import 'package:flowy_infra/theme_extension.dart';
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class NotificationItem extends StatefulWidget {
|
class NotificationItem extends StatefulWidget {
|
||||||
@ -71,6 +72,12 @@ class _NotificationItemState extends State<NotificationItem> {
|
|||||||
infoString = _buildInfoString();
|
infoString = _buildInfoString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
mutex.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
String _buildInfoString() {
|
String _buildInfoString() {
|
||||||
String scheduledString =
|
String scheduledString =
|
||||||
_scheduledString(widget.scheduled, widget.includeTime);
|
_scheduledString(widget.scheduled, widget.includeTime);
|
||||||
|
@ -0,0 +1,115 @@
|
|||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy/user/application/user_service.dart';
|
||||||
|
import 'package:appflowy/workspace/application/view/view_ext.dart';
|
||||||
|
import 'package:appflowy/workspace/application/view/view_service.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/settings/shared/settings_category.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/settings/shared/single_setting_action.dart';
|
||||||
|
import 'package:appflowy_backend/log.dart';
|
||||||
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
|
import 'package:appflowy_result/appflowy_result.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class FixDataWidget extends StatelessWidget {
|
||||||
|
const FixDataWidget({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SettingsCategory(
|
||||||
|
title: LocaleKeys.settings_manageDataPage_data_fixYourData.tr(),
|
||||||
|
children: [
|
||||||
|
SingleSettingAction(
|
||||||
|
labelMaxLines: 4,
|
||||||
|
label: LocaleKeys.settings_manageDataPage_data_fixYourDataDescription
|
||||||
|
.tr(),
|
||||||
|
buttonLabel: LocaleKeys.settings_manageDataPage_data_fixButton.tr(),
|
||||||
|
onPressed: () {
|
||||||
|
FixDataManager.checkWorkspaceHealth(dryRun: true);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FixDataManager {
|
||||||
|
static Future<void> checkWorkspaceHealth({
|
||||||
|
required bool dryRun,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
final currentWorkspace =
|
||||||
|
await UserBackendService.getCurrentWorkspace().getOrThrow();
|
||||||
|
// get all the views in the workspace
|
||||||
|
final result = await ViewBackendService.getAllViews().getOrThrow();
|
||||||
|
final allViews = result.items;
|
||||||
|
|
||||||
|
// dump all the views in the workspace
|
||||||
|
dumpViews('all views', allViews);
|
||||||
|
|
||||||
|
// get the workspace
|
||||||
|
final workspaces = allViews.where(
|
||||||
|
(e) => e.parentViewId == '' && e.id == currentWorkspace.id,
|
||||||
|
);
|
||||||
|
dumpViews('workspaces', workspaces.toList());
|
||||||
|
|
||||||
|
if (workspaces.length != 1) {
|
||||||
|
Log.error('Failed to fix workspace: workspace not found');
|
||||||
|
// there should be only one workspace
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final workspace = workspaces.first;
|
||||||
|
|
||||||
|
// check the health of the spaces
|
||||||
|
await checkSpaceHealth(workspace: workspace, allViews: allViews);
|
||||||
|
|
||||||
|
// add other checks here
|
||||||
|
// ...
|
||||||
|
} catch (e) {
|
||||||
|
Log.error('Failed to fix space relation: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> checkSpaceHealth({
|
||||||
|
required ViewPB workspace,
|
||||||
|
required List<ViewPB> allViews,
|
||||||
|
bool dryRun = true,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
final workspaceChildViews =
|
||||||
|
await ViewBackendService.getChildViews(viewId: workspace.id)
|
||||||
|
.getOrThrow();
|
||||||
|
final workspaceChildViewIds =
|
||||||
|
workspaceChildViews.map((e) => e.id).toSet();
|
||||||
|
final spaces = allViews.where((e) => e.isSpace).toList();
|
||||||
|
|
||||||
|
//
|
||||||
|
for (final space in spaces) {
|
||||||
|
// the space is the top level view, so its parent view id should be the workspace id
|
||||||
|
// and the workspace should have the space in its child views
|
||||||
|
if (space.parentViewId != workspace.id ||
|
||||||
|
!workspaceChildViewIds.contains(space.id)) {
|
||||||
|
Log.info('found an issue: space is not in the workspace: $space');
|
||||||
|
if (!dryRun) {
|
||||||
|
// move the space to the workspace if it is not in the workspace
|
||||||
|
await ViewBackendService.moveViewV2(
|
||||||
|
viewId: space.id,
|
||||||
|
newParentId: workspace.id,
|
||||||
|
prevViewId: null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
workspaceChildViewIds.add(space.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
Log.error('Failed to check space health: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dumpViews(String prefix, List<ViewPB> views) {
|
||||||
|
for (int i = 0; i < views.length; i++) {
|
||||||
|
final view = views[i];
|
||||||
|
Log.info('$prefix $i: $view)');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,13 @@
|
|||||||
import 'package:appflowy/workspace/presentation/settings/shared/af_dropdown_menu_entry.dart';
|
|
||||||
import 'package:appflowy/workspace/presentation/settings/shared/settings_dropdown.dart';
|
|
||||||
import 'package:appflowy_backend/log.dart';
|
|
||||||
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/ai/settings_ai_bloc.dart';
|
import 'package:appflowy/workspace/application/settings/ai/settings_ai_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_body.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/settings/shared/settings_dropdown.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart';
|
import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart';
|
||||||
|
import 'package:appflowy_backend/log.dart';
|
||||||
|
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
@ -153,11 +153,9 @@ class _AISearchToggle extends StatelessWidget {
|
|||||||
} else {
|
} else {
|
||||||
return Toggle(
|
return Toggle(
|
||||||
value: state.enableSearchIndexing,
|
value: state.enableSearchIndexing,
|
||||||
onChanged: (_) {
|
onChanged: (_) => context
|
||||||
context.read<SettingsAIBloc>().add(
|
.read<SettingsAIBloc>()
|
||||||
const SettingsAIEvent.toggleAISearch(),
|
.add(const SettingsAIEvent.toggleAISearch()),
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import 'package:appflowy/core/helpers/url_launcher.dart';
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
@ -13,6 +10,7 @@ import 'package:appflowy/util/theme_extension.dart';
|
|||||||
import 'package:appflowy/workspace/application/settings/setting_file_importer_bloc.dart';
|
import 'package:appflowy/workspace/application/settings/setting_file_importer_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/settings_location_cubit.dart';
|
import 'package:appflowy/workspace/application/settings/settings_location_cubit.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/toast.dart';
|
import 'package:appflowy/workspace/presentation/home/toast.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/settings/pages/fix_data_widget.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/shared/setting_action.dart';
|
import 'package:appflowy/workspace/presentation/settings/shared/setting_action.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/shared/settings_alert_dialog.dart';
|
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_body.dart';
|
||||||
@ -29,6 +27,8 @@ import 'package:flowy_infra_ui/style_widget/button.dart';
|
|||||||
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:fluttertoast/fluttertoast.dart';
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
|
|
||||||
@ -110,7 +110,10 @@ class SettingsManageDataView extends StatelessWidget {
|
|||||||
if (kDebugMode) ...[
|
if (kDebugMode) ...[
|
||||||
SettingsCategory(
|
SettingsCategory(
|
||||||
title: LocaleKeys.settings_files_exportData.tr(),
|
title: LocaleKeys.settings_files_exportData.tr(),
|
||||||
children: const [SettingsExportFileWidget()],
|
children: const [
|
||||||
|
SettingsExportFileWidget(),
|
||||||
|
FixDataWidget(),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
SettingsCategory(
|
SettingsCategory(
|
||||||
|
@ -47,7 +47,7 @@ class _SettingsPlanComparisonDialogState
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final isLM = Theme.of(context).isLightMode;
|
final isLM = Theme.of(context).isLightMode;
|
||||||
|
|
||||||
return BlocListener<SettingsPlanBloc, SettingsPlanState>(
|
return BlocConsumer<SettingsPlanBloc, SettingsPlanState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
final readyState = state.mapOrNull(ready: (state) => state);
|
final readyState = state.mapOrNull(ready: (state) => state);
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ class _SettingsPlanComparisonDialogState
|
|||||||
currentSubscription = readyState.subscription;
|
currentSubscription = readyState.subscription;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: FlowyDialog(
|
builder: (context, state) => FlowyDialog(
|
||||||
constraints: const BoxConstraints(maxWidth: 784, minWidth: 674),
|
constraints: const BoxConstraints(maxWidth: 784, minWidth: 674),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@ -185,7 +185,16 @@ class _SettingsPlanComparisonDialogState
|
|||||||
canDowngrade:
|
canDowngrade:
|
||||||
currentSubscription.subscriptionPlan !=
|
currentSubscription.subscriptionPlan !=
|
||||||
SubscriptionPlanPB.None,
|
SubscriptionPlanPB.None,
|
||||||
currentCanceled: currentSubscription.hasCanceled,
|
currentCanceled: currentSubscription.hasCanceled ||
|
||||||
|
(context
|
||||||
|
.watch<SettingsPlanBloc>()
|
||||||
|
.state
|
||||||
|
.mapOrNull(
|
||||||
|
loading: (_) => true,
|
||||||
|
ready: (state) =>
|
||||||
|
state.downgradeProcessing,
|
||||||
|
) ??
|
||||||
|
false),
|
||||||
onSelected: () async {
|
onSelected: () async {
|
||||||
if (currentSubscription.subscriptionPlan ==
|
if (currentSubscription.subscriptionPlan ==
|
||||||
SubscriptionPlanPB.None ||
|
SubscriptionPlanPB.None ||
|
||||||
@ -484,8 +493,9 @@ class _ActionButton extends StatelessWidget {
|
|||||||
cursor: onPressed != null
|
cursor: onPressed != null
|
||||||
? SystemMouseCursors.click
|
? SystemMouseCursors.click
|
||||||
: MouseCursor.defer,
|
: MouseCursor.defer,
|
||||||
child: _drawGradientBorder(
|
child: _drawBorder(
|
||||||
isLM: isLM,
|
isLM: isLM,
|
||||||
|
isUpgrade: isUpgrade,
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 36,
|
height: 36,
|
||||||
width: 148,
|
width: 148,
|
||||||
@ -496,9 +506,7 @@ class _ActionButton extends StatelessWidget {
|
|||||||
border: Border.all(color: Colors.transparent),
|
border: Border.all(color: Colors.transparent),
|
||||||
borderRadius: BorderRadius.circular(14),
|
borderRadius: BorderRadius.circular(14),
|
||||||
),
|
),
|
||||||
child: Center(
|
child: Center(child: _drawText(label, isLM, isUpgrade)),
|
||||||
child: _drawText(label, isLM),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -509,13 +517,13 @@ class _ActionButton extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _drawText(String text, bool isLM) {
|
Widget _drawText(String text, bool isLM, bool isUpgrade) {
|
||||||
final child = FlowyText(
|
final child = FlowyText(
|
||||||
text,
|
text,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
lineHeight: 1.2,
|
lineHeight: 1.2,
|
||||||
fontWeight: useGradientBorder ? FontWeight.w600 : FontWeight.w500,
|
fontWeight: useGradientBorder ? FontWeight.w600 : FontWeight.w500,
|
||||||
color: const Color(0xFFC49BEC),
|
color: isUpgrade ? const Color(0xFFC49BEC) : null,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!useGradientBorder || !isLM) {
|
if (!useGradientBorder || !isLM) {
|
||||||
@ -536,18 +544,25 @@ class _ActionButton extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _drawGradientBorder({required bool isLM, required Widget child}) {
|
Widget _drawBorder({
|
||||||
|
required bool isLM,
|
||||||
|
required bool isUpgrade,
|
||||||
|
required Widget child,
|
||||||
|
}) {
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(2),
|
padding: const EdgeInsets.all(2),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
gradient: LinearGradient(
|
gradient: isUpgrade
|
||||||
transform: const GradientRotation(-1.2),
|
? LinearGradient(
|
||||||
stops: const [0.4, 1],
|
transform: const GradientRotation(-1.2),
|
||||||
colors: [
|
stops: const [0.4, 1],
|
||||||
isLM ? const Color(0xFF251D37) : const Color(0xFF7459AD),
|
colors: [
|
||||||
isLM ? const Color(0xFF7547C0) : const Color(0xFFDDC8FF),
|
isLM ? const Color(0xFF251D37) : const Color(0xFF7459AD),
|
||||||
],
|
isLM ? const Color(0xFF7547C0) : const Color(0xFFDDC8FF),
|
||||||
),
|
],
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
border: isUpgrade ? null : Border.all(),
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
),
|
),
|
||||||
child: child,
|
child: child,
|
||||||
|
@ -80,11 +80,30 @@ class SettingsPlanView extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CurrentPlanBox extends StatelessWidget {
|
class _CurrentPlanBox extends StatefulWidget {
|
||||||
const _CurrentPlanBox({required this.subscription});
|
const _CurrentPlanBox({required this.subscription});
|
||||||
|
|
||||||
final WorkspaceSubscriptionPB subscription;
|
final WorkspaceSubscriptionPB subscription;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_CurrentPlanBox> createState() => _CurrentPlanBoxState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CurrentPlanBoxState extends State<_CurrentPlanBox> {
|
||||||
|
late SettingsPlanBloc planBloc;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
planBloc = context.read<SettingsPlanBloc>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
planBloc = context.read<SettingsPlanBloc>();
|
||||||
|
super.didChangeDependencies();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Stack(
|
return Stack(
|
||||||
@ -105,13 +124,13 @@ class _CurrentPlanBox extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
const VSpace(4),
|
const VSpace(4),
|
||||||
FlowyText.semibold(
|
FlowyText.semibold(
|
||||||
subscription.label,
|
widget.subscription.label,
|
||||||
fontSize: 24,
|
fontSize: 24,
|
||||||
color: AFThemeExtension.of(context).strongText,
|
color: AFThemeExtension.of(context).strongText,
|
||||||
),
|
),
|
||||||
const VSpace(8),
|
const VSpace(8),
|
||||||
FlowyText.regular(
|
FlowyText.regular(
|
||||||
subscription.info,
|
widget.subscription.info,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: AFThemeExtension.of(context).strongText,
|
color: AFThemeExtension.of(context).strongText,
|
||||||
maxLines: 3,
|
maxLines: 3,
|
||||||
@ -124,10 +143,10 @@ class _CurrentPlanBox extends StatelessWidget {
|
|||||||
onPressed: () => _openPricingDialog(
|
onPressed: () => _openPricingDialog(
|
||||||
context,
|
context,
|
||||||
context.read<SettingsPlanBloc>().workspaceId,
|
context.read<SettingsPlanBloc>().workspaceId,
|
||||||
subscription,
|
widget.subscription,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (subscription.hasCanceled) ...[
|
if (widget.subscription.hasCanceled) ...[
|
||||||
const VSpace(12),
|
const VSpace(12),
|
||||||
FlowyText(
|
FlowyText(
|
||||||
LocaleKeys
|
LocaleKeys
|
||||||
@ -149,10 +168,10 @@ class _CurrentPlanBox extends StatelessWidget {
|
|||||||
separatorBuilder: () => const VSpace(4),
|
separatorBuilder: () => const VSpace(4),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
..._getPros(subscription.subscriptionPlan).map(
|
..._getPros(widget.subscription.subscriptionPlan).map(
|
||||||
(s) => _ProConItem(label: s),
|
(s) => _ProConItem(label: s),
|
||||||
),
|
),
|
||||||
..._getCons(subscription.subscriptionPlan).map(
|
..._getCons(widget.subscription.subscriptionPlan).map(
|
||||||
(s) => _ProConItem(label: s, isPro: false),
|
(s) => _ProConItem(label: s, isPro: false),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -185,7 +204,7 @@ class _CurrentPlanBox extends StatelessWidget {
|
|||||||
String _canceledDate(BuildContext context) {
|
String _canceledDate(BuildContext context) {
|
||||||
final appearance = context.read<AppearanceSettingsCubit>().state;
|
final appearance = context.read<AppearanceSettingsCubit>().state;
|
||||||
return appearance.dateFormat.formatDate(
|
return appearance.dateFormat.formatDate(
|
||||||
subscription.canceledAt.toDateTime(),
|
widget.subscription.canceledAt.toDateTime(),
|
||||||
true,
|
true,
|
||||||
appearance.timeFormat,
|
appearance.timeFormat,
|
||||||
);
|
);
|
||||||
@ -199,7 +218,7 @@ class _CurrentPlanBox extends StatelessWidget {
|
|||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (_) => BlocProvider<SettingsPlanBloc>.value(
|
builder: (_) => BlocProvider<SettingsPlanBloc>.value(
|
||||||
value: context.read<SettingsPlanBloc>(),
|
value: planBloc,
|
||||||
child: SettingsPlanComparisonDialog(
|
child: SettingsPlanComparisonDialog(
|
||||||
workspaceId: workspaceId,
|
workspaceId: workspaceId,
|
||||||
subscription: subscription,
|
subscription: subscription,
|
||||||
@ -224,6 +243,7 @@ class _CurrentPlanBox extends StatelessWidget {
|
|||||||
LocaleKeys.settings_planPage_planUsage_currentPlan_freeProFour.tr(),
|
LocaleKeys.settings_planPage_planUsage_currentPlan_freeProFour.tr(),
|
||||||
LocaleKeys.settings_planPage_planUsage_currentPlan_freeProFive.tr(),
|
LocaleKeys.settings_planPage_planUsage_currentPlan_freeProFive.tr(),
|
||||||
];
|
];
|
||||||
|
|
||||||
List<String> _freeCons() => [
|
List<String> _freeCons() => [
|
||||||
LocaleKeys.settings_planPage_planUsage_currentPlan_freeConOne.tr(),
|
LocaleKeys.settings_planPage_planUsage_currentPlan_freeConOne.tr(),
|
||||||
LocaleKeys.settings_planPage_planUsage_currentPlan_freeConTwo.tr(),
|
LocaleKeys.settings_planPage_planUsage_currentPlan_freeConTwo.tr(),
|
||||||
@ -242,6 +262,7 @@ class _CurrentPlanBox extends StatelessWidget {
|
|||||||
LocaleKeys.settings_planPage_planUsage_currentPlan_professionalProFive
|
LocaleKeys.settings_planPage_planUsage_currentPlan_professionalProFive
|
||||||
.tr(),
|
.tr(),
|
||||||
];
|
];
|
||||||
|
|
||||||
List<String> _proCons() => [
|
List<String> _proCons() => [
|
||||||
LocaleKeys.settings_planPage_planUsage_currentPlan_professionalConOne
|
LocaleKeys.settings_planPage_planUsage_currentPlan_professionalConOne
|
||||||
.tr(),
|
.tr(),
|
||||||
@ -314,6 +335,11 @@ class _PlanUsageSummary extends StatelessWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: _UsageBox(
|
child: _UsageBox(
|
||||||
title: LocaleKeys.settings_planPage_planUsage_storageLabel.tr(),
|
title: LocaleKeys.settings_planPage_planUsage_storageLabel.tr(),
|
||||||
|
replacementText: subscription.subscriptionPlan ==
|
||||||
|
SubscriptionPlanPB.Pro
|
||||||
|
? LocaleKeys.settings_planPage_planUsage_storageUnlimited
|
||||||
|
.tr()
|
||||||
|
: null,
|
||||||
label: LocaleKeys.settings_planPage_planUsage_storageUsage.tr(
|
label: LocaleKeys.settings_planPage_planUsage_storageUsage.tr(
|
||||||
args: [
|
args: [
|
||||||
usage.currentBlobInGb,
|
usage.currentBlobInGb,
|
||||||
@ -372,12 +398,16 @@ class _UsageBox extends StatelessWidget {
|
|||||||
required this.title,
|
required this.title,
|
||||||
required this.label,
|
required this.label,
|
||||||
required this.value,
|
required this.value,
|
||||||
|
this.replacementText,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String title;
|
final String title;
|
||||||
final String label;
|
final String label;
|
||||||
final double value;
|
final double value;
|
||||||
|
|
||||||
|
/// Replaces the progress indicator if not null
|
||||||
|
final String? replacementText;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(
|
return Column(
|
||||||
@ -388,7 +418,21 @@ class _UsageBox extends StatelessWidget {
|
|||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
color: AFThemeExtension.of(context).secondaryTextColor,
|
color: AFThemeExtension.of(context).secondaryTextColor,
|
||||||
),
|
),
|
||||||
_PlanProgressIndicator(label: label, progress: value),
|
if (replacementText != null) ...[
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
child: FlowyText.medium(
|
||||||
|
replacementText!,
|
||||||
|
fontSize: 11,
|
||||||
|
color: AFThemeExtension.of(context).secondaryTextColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
] else ...[
|
||||||
|
_PlanProgressIndicator(label: label, progress: value),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/base/emoji/emoji_picker.dart';
|
import 'package:appflowy/plugins/base/emoji/emoji_picker.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/base/selectable_svg_widget.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/base/selectable_svg_widget.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/decoration.dart';
|
import 'package:flowy_infra_ui/style_widget/decoration.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
|
|
||||||
SelectionMenuItem emojiMenuItem = SelectionMenuItem(
|
SelectionMenuItem emojiMenuItem = SelectionMenuItem(
|
||||||
getName: LocaleKeys.document_plugins_emoji.tr,
|
getName: LocaleKeys.document_plugins_emoji.tr,
|
||||||
@ -85,8 +86,8 @@ class EmojiSelectionMenu extends StatefulWidget {
|
|||||||
class _EmojiSelectionMenuState extends State<EmojiSelectionMenu> {
|
class _EmojiSelectionMenuState extends State<EmojiSelectionMenu> {
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
HardwareKeyboard.instance.addHandler(_handleGlobalKeyEvent);
|
|
||||||
super.initState();
|
super.initState();
|
||||||
|
HardwareKeyboard.instance.addHandler(_handleGlobalKeyEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _handleGlobalKeyEvent(KeyEvent event) {
|
bool _handleGlobalKeyEvent(KeyEvent event) {
|
||||||
@ -95,9 +96,8 @@ class _EmojiSelectionMenuState extends State<EmojiSelectionMenu> {
|
|||||||
//triggers on esc
|
//triggers on esc
|
||||||
widget.onExit();
|
widget.onExit();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -106,17 +106,10 @@ class _EmojiSelectionMenuState extends State<EmojiSelectionMenu> {
|
|||||||
super.deactivate();
|
super.deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FlowyEmojiPicker(
|
return FlowyEmojiPicker(
|
||||||
onEmojiSelected: (_, emoji) {
|
onEmojiSelected: (_, emoji) => widget.onSubmitted(emoji),
|
||||||
widget.onSubmitted(emoji);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'emoji_picker.dart';
|
import 'emoji_picker.dart';
|
||||||
import 'emoji_picker_builder.dart';
|
import 'emoji_picker_builder.dart';
|
||||||
import 'models/emoji_category_models.dart';
|
import 'models/emoji_category_models.dart';
|
||||||
@ -29,8 +31,10 @@ class DefaultEmojiPickerViewState extends State<DefaultEmojiPickerView>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
var initCategory = widget.state.emojiCategoryGroupList.indexWhere(
|
super.initState();
|
||||||
(element) => element.category == widget.config.initCategory,
|
|
||||||
|
int initCategory = widget.state.emojiCategoryGroupList.indexWhere(
|
||||||
|
(el) => el.category == widget.config.initCategory,
|
||||||
);
|
);
|
||||||
if (initCategory == -1) {
|
if (initCategory == -1) {
|
||||||
initCategory = 0;
|
initCategory = 0;
|
||||||
@ -42,27 +46,23 @@ class DefaultEmojiPickerViewState extends State<DefaultEmojiPickerView>
|
|||||||
);
|
);
|
||||||
_pageController = PageController(initialPage: initCategory);
|
_pageController = PageController(initialPage: initCategory);
|
||||||
_emojiFocusNode.requestFocus();
|
_emojiFocusNode.requestFocus();
|
||||||
|
|
||||||
_emojiController.addListener(() {
|
_emojiController.addListener(() {
|
||||||
final String query = _emojiController.text.toLowerCase();
|
final String query = _emojiController.text.toLowerCase();
|
||||||
if (query.isEmpty) {
|
if (query.isEmpty) {
|
||||||
searchEmojiList.emoji.clear();
|
searchEmojiList.emoji.clear();
|
||||||
_pageController!.jumpToPage(
|
_pageController!.jumpToPage(_tabController!.index);
|
||||||
_tabController!.index,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
searchEmojiList.emoji.clear();
|
searchEmojiList.emoji.clear();
|
||||||
for (final element in widget.state.emojiCategoryGroupList) {
|
for (final element in widget.state.emojiCategoryGroupList) {
|
||||||
searchEmojiList.emoji.addAll(
|
searchEmojiList.emoji.addAll(
|
||||||
element.emoji.where((item) {
|
element.emoji
|
||||||
return item.name.toLowerCase().contains(query);
|
.where((item) => item.name.toLowerCase().contains(query))
|
||||||
}).toList(),
|
.toList(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setState(() {});
|
setState(() {});
|
||||||
});
|
});
|
||||||
super.initState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -81,25 +81,17 @@ class DefaultEmojiPickerViewState extends State<DefaultEmojiPickerView>
|
|||||||
type: MaterialType.transparency,
|
type: MaterialType.transparency,
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
padding: const EdgeInsets.only(bottom: 2),
|
padding: const EdgeInsets.only(bottom: 2),
|
||||||
icon: Icon(
|
icon: Icon(Icons.backspace, color: widget.config.backspaceColor),
|
||||||
Icons.backspace,
|
onPressed: () => widget.state.onBackspacePressed!(),
|
||||||
color: widget.config.backspaceColor,
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
widget.state.onBackspacePressed!();
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isEmojiSearching() {
|
bool isEmojiSearching() =>
|
||||||
final bool result =
|
searchEmojiList.emoji.isNotEmpty || _emojiController.text.isNotEmpty;
|
||||||
searchEmojiList.emoji.isNotEmpty || _emojiController.text.isNotEmpty;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -213,15 +205,9 @@ class DefaultEmojiPickerViewState extends State<DefaultEmojiPickerView>
|
|||||||
required Widget child,
|
required Widget child,
|
||||||
}) {
|
}) {
|
||||||
if (widget.config.buttonMode == ButtonMode.MATERIAL) {
|
if (widget.config.buttonMode == ButtonMode.MATERIAL) {
|
||||||
return InkWell(
|
return InkWell(onTap: onPressed, child: child);
|
||||||
onTap: onPressed,
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return GestureDetector(
|
return GestureDetector(onTap: onPressed, child: child);
|
||||||
onTap: onPressed,
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildPage(double emojiSize, EmojiCategoryGroup emojiCategoryGroup) {
|
Widget _buildPage(double emojiSize, EmojiCategoryGroup emojiCategoryGroup) {
|
||||||
@ -275,9 +261,7 @@ class DefaultEmojiPickerViewState extends State<DefaultEmojiPickerView>
|
|||||||
child: FittedBox(
|
child: FittedBox(
|
||||||
child: Text(
|
child: Text(
|
||||||
emoji.emoji,
|
emoji.emoji,
|
||||||
style: TextStyle(
|
style: TextStyle(fontSize: emojiSize),
|
||||||
fontSize: emojiSize,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
import 'package:flutter/gestures.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
import 'package:appflowy/core/helpers/url_launcher.dart';
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/supabase_cloud_setting_bloc.dart';
|
import 'package:appflowy/workspace/application/settings/supabase_cloud_setting_bloc.dart';
|
||||||
@ -15,9 +19,6 @@ import 'package:flowy_infra/theme_extension.dart';
|
|||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flowy_infra_ui/widget/error_page.dart';
|
import 'package:flowy_infra_ui/widget/error_page.dart';
|
||||||
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class SettingSupabaseCloudView extends StatelessWidget {
|
class SettingSupabaseCloudView extends StatelessWidget {
|
||||||
@ -265,13 +266,7 @@ class SupabaseInput extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class SupabaseInputState extends State<SupabaseInput> {
|
class SupabaseInputState extends State<SupabaseInput> {
|
||||||
late TextEditingController _controller;
|
late final _controller = TextEditingController(text: widget.url);
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_controller = TextEditingController(text: widget.url);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
@ -29,6 +29,12 @@ class _DateTimeSettingState extends State<DateTimeSetting> {
|
|||||||
final timeSettingPopoverMutex = PopoverMutex();
|
final timeSettingPopoverMutex = PopoverMutex();
|
||||||
String? overlayIdentifier;
|
String? overlayIdentifier;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
timeSettingPopoverMutex.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final List<Widget> children = [
|
final List<Widget> children = [
|
||||||
|
@ -129,11 +129,6 @@ class NavigatorAlertDialog extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _CreateFlowyAlertDialog extends State<NavigatorAlertDialog> {
|
class _CreateFlowyAlertDialog extends State<NavigatorAlertDialog> {
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return StyledDialog(
|
return StyledDialog(
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
class PopoverActionList<T extends PopoverAction> extends StatefulWidget {
|
class PopoverActionList<T extends PopoverAction> extends StatefulWidget {
|
||||||
@ -42,12 +43,12 @@ class PopoverActionList<T extends PopoverAction> extends StatefulWidget {
|
|||||||
|
|
||||||
class _PopoverActionListState<T extends PopoverAction>
|
class _PopoverActionListState<T extends PopoverAction>
|
||||||
extends State<PopoverActionList<T>> {
|
extends State<PopoverActionList<T>> {
|
||||||
late PopoverController popoverController;
|
final PopoverController popoverController = PopoverController();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void dispose() {
|
||||||
popoverController = PopoverController();
|
popoverController.close();
|
||||||
super.initState();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:appflowy/workspace/application/view/view_listener.dart';
|
import 'package:appflowy/workspace/application/view/view_listener.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class ViewTabBarItem extends StatefulWidget {
|
class ViewTabBarItem extends StatefulWidget {
|
||||||
const ViewTabBarItem({super.key, required this.view});
|
const ViewTabBarItem({super.key, required this.view});
|
||||||
@ -37,7 +38,5 @@ class _ViewTabBarItemState extends State<ViewTabBarItem> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) => FlowyText.medium(view.name);
|
||||||
return FlowyText.medium(view.name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
import 'package:appflowy_backend/appflowy_backend.dart';
|
import 'package:appflowy_backend/appflowy_backend.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
@ -36,21 +37,15 @@ class _MyAppState extends State<MyApp> {
|
|||||||
// message was in flight, we want to discard the reply rather than calling
|
// message was in flight, we want to discard the reply rather than calling
|
||||||
// setState to update our non-existent appearance.
|
// setState to update our non-existent appearance.
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
setState(() {
|
setState(() => _platformVersion = platformVersion);
|
||||||
_platformVersion = platformVersion;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
home: Scaffold(
|
home: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(title: const Text('Plugin example app')),
|
||||||
title: const Text('Plugin example app'),
|
body: Center(child: Text('Running on: $_platformVersion\n')),
|
||||||
),
|
|
||||||
body: Center(
|
|
||||||
child: Text('Running on: $_platformVersion\n'),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import 'package:appflowy_popover/src/layout.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
import 'package:appflowy_popover/src/layout.dart';
|
||||||
|
|
||||||
import 'mask.dart';
|
import 'mask.dart';
|
||||||
import 'mutex.dart';
|
import 'mutex.dart';
|
||||||
|
|
||||||
@ -177,9 +178,7 @@ class PopoverState extends State<Popover> {
|
|||||||
_rootEntry.addEntry(context, this, newEntry, widget.asBarrier);
|
_rootEntry.addEntry(context, this, newEntry, widget.asBarrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
void close({
|
void close({bool notify = true}) {
|
||||||
bool notify = true,
|
|
||||||
}) {
|
|
||||||
if (_rootEntry.contains(this)) {
|
if (_rootEntry.contains(this)) {
|
||||||
_rootEntry.removeEntry(this);
|
_rootEntry.removeEntry(this);
|
||||||
if (notify) {
|
if (notify) {
|
||||||
@ -286,9 +285,7 @@ class PopoverContainer extends StatefulWidget {
|
|||||||
if (context is StatefulElement && context.state is PopoverContainerState) {
|
if (context is StatefulElement && context.state is PopoverContainerState) {
|
||||||
return context.state as PopoverContainerState;
|
return context.state as PopoverContainerState;
|
||||||
}
|
}
|
||||||
final PopoverContainerState? result =
|
return context.findAncestorStateOfType<PopoverContainerState>()!;
|
||||||
context.findAncestorStateOfType<PopoverContainerState>();
|
|
||||||
return result!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PopoverContainerState? maybeOf(BuildContext context) {
|
static PopoverContainerState? maybeOf(BuildContext context) {
|
||||||
|
@ -2,10 +2,11 @@
|
|||||||
|
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:flowy_infra_ui/src/flowy_overlay/layout.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
import 'package:flowy_infra_ui/src/flowy_overlay/layout.dart';
|
||||||
|
|
||||||
/// Specifies how overlay are anchored to the SourceWidget
|
/// Specifies how overlay are anchored to the SourceWidget
|
||||||
enum AnchorDirection {
|
enum AnchorDirection {
|
||||||
// Corner aligned with a corner of the SourceWidget
|
// Corner aligned with a corner of the SourceWidget
|
||||||
@ -341,18 +342,17 @@ class FlowyOverlayState extends State<FlowyOverlay> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_keyboardShortcutBindings.addAll({
|
|
||||||
LogicalKeySet(LogicalKeyboardKey.escape): (identifier) {
|
|
||||||
remove(identifier);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_keyboardShortcutBindings.addAll({
|
||||||
|
LogicalKeySet(LogicalKeyboardKey.escape): (identifier) =>
|
||||||
|
remove(identifier),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final overlays = _overlayList.map((item) {
|
final overlays = _overlayList.map((item) {
|
||||||
var widget = item.widget;
|
Widget widget = item.widget;
|
||||||
|
|
||||||
// requestFocus will cause the children weird focus behaviors.
|
// requestFocus will cause the children weird focus behaviors.
|
||||||
// item.focusNode.requestFocus();
|
// item.focusNode.requestFocus();
|
||||||
@ -390,15 +390,11 @@ class FlowyOverlayState extends State<FlowyOverlay> {
|
|||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
theme: Theme.of(context),
|
theme: Theme.of(context),
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
home: Stack(
|
home: Stack(children: children..addAll(overlays)),
|
||||||
children: children..addAll(overlays),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleTapOnBackground() {
|
void _handleTapOnBackground() => removeAll();
|
||||||
removeAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget? _renderBackground(List<Widget> overlays) {
|
Widget? _renderBackground(List<Widget> overlays) {
|
||||||
Widget? child;
|
Widget? child;
|
||||||
|
@ -36,13 +36,7 @@ class StyledListView extends StatefulWidget {
|
|||||||
|
|
||||||
/// State is public so this can easily be controlled externally
|
/// State is public so this can easily be controlled externally
|
||||||
class StyledListViewState extends State<StyledListView> {
|
class StyledListViewState extends State<StyledListView> {
|
||||||
late ScrollController scrollController;
|
final scrollController = ScrollController();
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
scrollController = ScrollController();
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
@ -50,15 +44,6 @@ class StyledListViewState extends State<StyledListView> {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void didUpdateWidget(StyledListView oldWidget) {
|
|
||||||
if (oldWidget.itemCount != widget.itemCount ||
|
|
||||||
oldWidget.itemExtent != widget.itemExtent) {
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
super.didUpdateWidget(oldWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final contentSize = (widget.itemCount ?? 0.0) * (widget.itemExtent ?? 00.0);
|
final contentSize = (widget.itemCount ?? 0.0) * (widget.itemExtent ?? 00.0);
|
||||||
@ -75,7 +60,7 @@ class StyledListViewState extends State<StyledListView> {
|
|||||||
controller: scrollController,
|
controller: scrollController,
|
||||||
itemExtent: widget.itemExtent,
|
itemExtent: widget.itemExtent,
|
||||||
itemCount: widget.itemCount,
|
itemCount: widget.itemCount,
|
||||||
itemBuilder: (c, i) => widget.itemBuilder(c, i),
|
itemBuilder: widget.itemBuilder,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return listContent;
|
return listContent;
|
||||||
|
@ -137,7 +137,6 @@ class FlowyTextFieldState extends State<FlowyTextField> {
|
|||||||
void _onSubmitted(String text) {
|
void _onSubmitted(String text) {
|
||||||
widget.onSubmitted?.call(text);
|
widget.onSubmitted?.call(text);
|
||||||
if (widget.autoClearWhenDone) {
|
if (widget.autoClearWhenDone) {
|
||||||
// using `controller.clear()` instead of `controller.text = ''` which will crash on Windows.
|
|
||||||
controller.clear();
|
controller.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,7 +153,7 @@ class FlowyTextFieldState extends State<FlowyTextField> {
|
|||||||
_onChanged(text);
|
_onChanged(text);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSubmitted: (text) => _onSubmitted(text),
|
onSubmitted: _onSubmitted,
|
||||||
onEditingComplete: widget.onEditingComplete,
|
onEditingComplete: widget.onEditingComplete,
|
||||||
minLines: 1,
|
minLines: 1,
|
||||||
maxLines: widget.maxLines,
|
maxLines: widget.maxLines,
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
|
|
||||||
import 'package:flowy_infra/size.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
import 'package:flowy_infra/size.dart';
|
||||||
|
|
||||||
class FlowyFormTextInput extends StatelessWidget {
|
class FlowyFormTextInput extends StatelessWidget {
|
||||||
static EdgeInsets kDefaultTextInputPadding =
|
static EdgeInsets kDefaultTextInputPadding =
|
||||||
EdgeInsets.only(bottom: Insets.sm, top: 4);
|
EdgeInsets.only(bottom: Insets.sm, top: 4);
|
||||||
@ -162,10 +163,12 @@ class StyledSearchTextInputState extends State<StyledSearchTextInput> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
super.initState();
|
||||||
_controller =
|
_controller =
|
||||||
widget.controller ?? TextEditingController(text: widget.initialValue);
|
widget.controller ?? TextEditingController(text: widget.initialValue);
|
||||||
_focusNode = FocusNode(
|
_focusNode = FocusNode(
|
||||||
debugLabel: widget.label ?? '',
|
debugLabel: widget.label,
|
||||||
|
canRequestFocus: true,
|
||||||
onKeyEvent: (node, event) {
|
onKeyEvent: (node, event) {
|
||||||
if (event.logicalKey == LogicalKeyboardKey.escape) {
|
if (event.logicalKey == LogicalKeyboardKey.escape) {
|
||||||
widget.onEditingCancel?.call();
|
widget.onEditingCancel?.call();
|
||||||
@ -173,7 +176,6 @@ class StyledSearchTextInputState extends State<StyledSearchTextInput> {
|
|||||||
}
|
}
|
||||||
return KeyEventResult.ignored;
|
return KeyEventResult.ignored;
|
||||||
},
|
},
|
||||||
canRequestFocus: true,
|
|
||||||
);
|
);
|
||||||
// Listen for focus out events
|
// Listen for focus out events
|
||||||
_focusNode
|
_focusNode
|
||||||
@ -182,7 +184,6 @@ class StyledSearchTextInputState extends State<StyledSearchTextInput> {
|
|||||||
if (widget.autoFocus ?? false) {
|
if (widget.autoFocus ?? false) {
|
||||||
scheduleMicrotask(() => _focusNode.requestFocus());
|
scheduleMicrotask(() => _focusNode.requestFocus());
|
||||||
}
|
}
|
||||||
super.initState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -292,8 +293,10 @@ class ThinUnderlineBorder extends InputBorder {
|
|||||||
bool get isOutline => false;
|
bool get isOutline => false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
UnderlineInputBorder copyWith(
|
UnderlineInputBorder copyWith({
|
||||||
{BorderSide? borderSide, BorderRadius? borderRadius}) {
|
BorderSide? borderSide,
|
||||||
|
BorderRadius? borderRadius,
|
||||||
|
}) {
|
||||||
return UnderlineInputBorder(
|
return UnderlineInputBorder(
|
||||||
borderSide: borderSide ?? this.borderSide,
|
borderSide: borderSide ?? this.borderSide,
|
||||||
borderRadius: borderRadius ?? this.borderRadius,
|
borderRadius: borderRadius ?? this.borderRadius,
|
||||||
@ -301,14 +304,12 @@ class ThinUnderlineBorder extends InputBorder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
EdgeInsetsGeometry get dimensions {
|
EdgeInsetsGeometry get dimensions =>
|
||||||
return EdgeInsets.only(bottom: borderSide.width);
|
EdgeInsets.only(bottom: borderSide.width);
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
UnderlineInputBorder scale(double t) {
|
UnderlineInputBorder scale(double t) =>
|
||||||
return UnderlineInputBorder(borderSide: borderSide.scale(t));
|
UnderlineInputBorder(borderSide: borderSide.scale(t));
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Path getInnerPath(Rect rect, {TextDirection? textDirection}) {
|
Path getInnerPath(Rect rect, {TextDirection? textDirection}) {
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import 'package:flowy_infra/size.dart';
|
|
||||||
import 'package:flowy_infra_ui/widget/rounded_button.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flowy_infra/time/duration.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
import 'package:flowy_infra/size.dart';
|
||||||
|
import 'package:flowy_infra/time/duration.dart';
|
||||||
|
import 'package:flowy_infra_ui/widget/rounded_button.dart';
|
||||||
|
|
||||||
class RoundedInputField extends StatefulWidget {
|
class RoundedInputField extends StatefulWidget {
|
||||||
final String? hintText;
|
final String? hintText;
|
||||||
final bool obscureText;
|
final bool obscureText;
|
||||||
@ -60,33 +61,26 @@ class RoundedInputField extends StatefulWidget {
|
|||||||
|
|
||||||
class _RoundedInputFieldState extends State<RoundedInputField> {
|
class _RoundedInputFieldState extends State<RoundedInputField> {
|
||||||
String inputText = "";
|
String inputText = "";
|
||||||
bool obscuteText = false;
|
bool obscureText = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
obscuteText = widget.obscureText;
|
|
||||||
if (widget.controller != null) {
|
|
||||||
inputText = widget.controller!.text;
|
|
||||||
} else {
|
|
||||||
inputText = widget.initialValue ?? "";
|
|
||||||
}
|
|
||||||
|
|
||||||
super.initState();
|
super.initState();
|
||||||
|
obscureText = widget.obscureText;
|
||||||
|
inputText = widget.controller != null
|
||||||
|
? widget.controller!.text
|
||||||
|
: widget.initialValue ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
String? _suffixText() {
|
String? _suffixText() => widget.maxLength != null
|
||||||
if (widget.maxLength != null) {
|
? ' ${widget.controller!.text.length}/${widget.maxLength}'
|
||||||
return ' ${widget.controller!.text.length}/${widget.maxLength}';
|
: null;
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var borderColor =
|
Color borderColor =
|
||||||
widget.normalBorderColor ?? Theme.of(context).colorScheme.outline;
|
widget.normalBorderColor ?? Theme.of(context).colorScheme.outline;
|
||||||
var focusBorderColor =
|
Color focusBorderColor =
|
||||||
widget.focusBorderColor ?? Theme.of(context).colorScheme.primary;
|
widget.focusBorderColor ?? Theme.of(context).colorScheme.primary;
|
||||||
|
|
||||||
if (widget.errorText.isNotEmpty) {
|
if (widget.errorText.isNotEmpty) {
|
||||||
@ -122,7 +116,7 @@ class _RoundedInputFieldState extends State<RoundedInputField> {
|
|||||||
},
|
},
|
||||||
cursorColor:
|
cursorColor:
|
||||||
widget.cursorColor ?? Theme.of(context).colorScheme.primary,
|
widget.cursorColor ?? Theme.of(context).colorScheme.primary,
|
||||||
obscureText: obscuteText,
|
obscureText: obscureText,
|
||||||
style: widget.style ?? Theme.of(context).textTheme.bodyMedium,
|
style: widget.style ?? Theme.of(context).textTheme.bodyMedium,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
contentPadding: widget.contentPadding,
|
contentPadding: widget.contentPadding,
|
||||||
@ -134,17 +128,11 @@ class _RoundedInputFieldState extends State<RoundedInputField> {
|
|||||||
suffixText: _suffixText(),
|
suffixText: _suffixText(),
|
||||||
counterText: "",
|
counterText: "",
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(color: borderColor, width: 1.0),
|
||||||
color: borderColor,
|
|
||||||
width: 1.0,
|
|
||||||
),
|
|
||||||
borderRadius: Corners.s10Border,
|
borderRadius: Corners.s10Border,
|
||||||
),
|
),
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(color: focusBorderColor, width: 1.0),
|
||||||
color: focusBorderColor,
|
|
||||||
width: 1.0,
|
|
||||||
),
|
|
||||||
borderRadius: Corners.s10Border,
|
borderRadius: Corners.s10Border,
|
||||||
),
|
),
|
||||||
suffixIcon: obscureIcon(),
|
suffixIcon: obscureIcon(),
|
||||||
@ -186,19 +174,11 @@ class _RoundedInputFieldState extends State<RoundedInputField> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert(widget.obscureIcon != null && widget.obscureHideIcon != null);
|
assert(widget.obscureIcon != null && widget.obscureHideIcon != null);
|
||||||
Widget? icon;
|
final icon = obscureText ? widget.obscureIcon! : widget.obscureHideIcon!;
|
||||||
if (obscuteText) {
|
|
||||||
icon = widget.obscureIcon!;
|
|
||||||
} else {
|
|
||||||
icon = widget.obscureHideIcon!;
|
|
||||||
}
|
|
||||||
|
|
||||||
return RoundedImageButton(
|
return RoundedImageButton(
|
||||||
size: iconWidth,
|
size: iconWidth,
|
||||||
press: () {
|
press: () => setState(() => obscureText = !obscureText),
|
||||||
obscuteText = !obscuteText;
|
|
||||||
setState(() {});
|
|
||||||
},
|
|
||||||
child: icon,
|
child: icon,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -53,11 +53,11 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: "."
|
path: "."
|
||||||
ref: "64c0be8"
|
ref: e8ee051
|
||||||
resolved-ref: "64c0be88a113c2eece5512701527e7d11b8c9239"
|
resolved-ref: e8ee051719eded6621ccdc2722f696411c020209
|
||||||
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
|
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
|
||||||
source: git
|
source: git
|
||||||
version: "2.5.1"
|
version: "3.0.0"
|
||||||
appflowy_editor_plugins:
|
appflowy_editor_plugins:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
|||||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||||
# Read more about iOS versioning at
|
# Read more about iOS versioning at
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
version: 0.6.1
|
version: 0.6.2
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
flutter: ">=3.22.0"
|
flutter: ">=3.22.0"
|
||||||
@ -186,7 +186,7 @@ dependency_overrides:
|
|||||||
appflowy_editor:
|
appflowy_editor:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/AppFlowy-IO/appflowy-editor.git
|
url: https://github.com/AppFlowy-IO/appflowy-editor.git
|
||||||
ref: "64c0be8"
|
ref: "e8ee051"
|
||||||
|
|
||||||
appflowy_editor_plugins:
|
appflowy_editor_plugins:
|
||||||
git:
|
git:
|
||||||
|
@ -59,7 +59,7 @@ class AppFlowyUnitTest {
|
|||||||
|
|
||||||
WorkspacePB get currentWorkspace => workspace;
|
WorkspacePB get currentWorkspace => workspace;
|
||||||
Future<void> _loadWorkspace() async {
|
Future<void> _loadWorkspace() async {
|
||||||
final result = await userService.getCurrentWorkspace();
|
final result = await UserBackendService.getCurrentWorkspace();
|
||||||
result.fold(
|
result.fold(
|
||||||
(value) => workspace = value,
|
(value) => workspace = value,
|
||||||
(error) {
|
(error) {
|
||||||
|
@ -410,17 +410,6 @@
|
|||||||
"pleaseInputYourStabilityAIKey": "يرجى إدخال رمز Stability AI الخاص بك",
|
"pleaseInputYourStabilityAIKey": "يرجى إدخال رمز Stability AI الخاص بك",
|
||||||
"clickToLogout": "انقر لتسجيل خروج المستخدم الحالي"
|
"clickToLogout": "انقر لتسجيل خروج المستخدم الحالي"
|
||||||
},
|
},
|
||||||
"shortcuts": {
|
|
||||||
"shortcutsLabel": "الاختصارات",
|
|
||||||
"command": "امر",
|
|
||||||
"keyBinding": "ربط المفاتيح",
|
|
||||||
"addNewCommand": "إضافة أمر جديد",
|
|
||||||
"updateShortcutStep": "اضغط على مجموعة المفاتيح المطلوبة ثم اضغط على ENTER",
|
|
||||||
"shortcutIsAlreadyUsed": "هذا الاختصار مستخدم بالفعل لـ: {conflict}",
|
|
||||||
"resetToDefault": "إعادة التعيين إلى روابط المفاتيح الافتراضية",
|
|
||||||
"couldNotLoadErrorMsg": "تعذر تحميل الاختصارات، حاول مرة أخرى",
|
|
||||||
"couldNotSaveErrorMsg": "تعذر حفظ الاختصارات، حاول مرة أخرى"
|
|
||||||
},
|
|
||||||
"mobile": {
|
"mobile": {
|
||||||
"personalInfo": "معلومات شخصية",
|
"personalInfo": "معلومات شخصية",
|
||||||
"username": "اسم المستخدم",
|
"username": "اسم المستخدم",
|
||||||
@ -435,6 +424,17 @@
|
|||||||
"userprofileErrorDescription": "يرجى محاولة تسجيل الخروج وتسجيل الدخول مرة أخرى للتحقق مما إذا كانت المشكلة لا تزال قائمة.",
|
"userprofileErrorDescription": "يرجى محاولة تسجيل الخروج وتسجيل الدخول مرة أخرى للتحقق مما إذا كانت المشكلة لا تزال قائمة.",
|
||||||
"selectLayout": "حدد الشكل",
|
"selectLayout": "حدد الشكل",
|
||||||
"selectStartingDay": "اختر يوم البدء"
|
"selectStartingDay": "اختر يوم البدء"
|
||||||
|
},
|
||||||
|
"shortcuts": {
|
||||||
|
"shortcutsLabel": "الاختصارات",
|
||||||
|
"command": "امر",
|
||||||
|
"keyBinding": "ربط المفاتيح",
|
||||||
|
"addNewCommand": "إضافة أمر جديد",
|
||||||
|
"updateShortcutStep": "اضغط على مجموعة المفاتيح المطلوبة ثم اضغط على ENTER",
|
||||||
|
"shortcutIsAlreadyUsed": "هذا الاختصار مستخدم بالفعل لـ: {conflict}",
|
||||||
|
"resetToDefault": "إعادة التعيين إلى روابط المفاتيح الافتراضية",
|
||||||
|
"couldNotLoadErrorMsg": "تعذر تحميل الاختصارات، حاول مرة أخرى",
|
||||||
|
"couldNotSaveErrorMsg": "تعذر حفظ الاختصارات، حاول مرة أخرى"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid": {
|
"grid": {
|
||||||
|
@ -385,10 +385,6 @@
|
|||||||
"selectAnIcon": "Seleccioneu una icona",
|
"selectAnIcon": "Seleccioneu una icona",
|
||||||
"pleaseInputYourOpenAIKey": "si us plau, introduïu la vostra clau OpenAI"
|
"pleaseInputYourOpenAIKey": "si us plau, introduïu la vostra clau OpenAI"
|
||||||
},
|
},
|
||||||
"shortcuts": {
|
|
||||||
"command": "Comandament",
|
|
||||||
"addNewCommand": "Afegeix una comanda nova"
|
|
||||||
},
|
|
||||||
"mobile": {
|
"mobile": {
|
||||||
"personalInfo": "Informació personal",
|
"personalInfo": "Informació personal",
|
||||||
"username": "Nom d'usuari",
|
"username": "Nom d'usuari",
|
||||||
@ -402,6 +398,10 @@
|
|||||||
"userprofileError": "No s'ha pogut carregar el perfil d'usuari",
|
"userprofileError": "No s'ha pogut carregar el perfil d'usuari",
|
||||||
"selectStartingDay": "Seleccioneu el dia d'inici",
|
"selectStartingDay": "Seleccioneu el dia d'inici",
|
||||||
"version": "Versió"
|
"version": "Versió"
|
||||||
|
},
|
||||||
|
"shortcuts": {
|
||||||
|
"command": "Comandament",
|
||||||
|
"addNewCommand": "Afegeix una comanda nova"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid": {
|
"grid": {
|
||||||
|
@ -484,17 +484,6 @@
|
|||||||
"pleaseInputYourStabilityAIKey": "تکایە جێگیری کلیلی AI ـەکەت بنووسە",
|
"pleaseInputYourStabilityAIKey": "تکایە جێگیری کلیلی AI ـەکەت بنووسە",
|
||||||
"clickToLogout": "بۆ دەرچوون لە بەکارهێنەری ئێستا کلیک بکە"
|
"clickToLogout": "بۆ دەرچوون لە بەکارهێنەری ئێستا کلیک بکە"
|
||||||
},
|
},
|
||||||
"shortcuts": {
|
|
||||||
"shortcutsLabel": "کورتە ڕێگاکان",
|
|
||||||
"command": "فەرمان",
|
|
||||||
"keyBinding": "کورتکراوەکانی تەختەکلیل",
|
|
||||||
"addNewCommand": "زیاد کردنی فەرمانێکی نوێ",
|
|
||||||
"updateShortcutStep": "تێکەڵەی کلیلی دڵخواز داگرە و ENTER داگرە",
|
|
||||||
"shortcutIsAlreadyUsed": "ئەم کورتە ڕێگایە پێشتر بۆ: {conflict} بەکارهاتووە.",
|
|
||||||
"resetToDefault": "گەڕاندنەوە بۆ کلیلەکانی بنهڕهت",
|
|
||||||
"couldNotLoadErrorMsg": "کورتە ڕێگاکان نەتوانرا باربکرێن، تکایە دووبارە هەوڵبدەرەوە",
|
|
||||||
"couldNotSaveErrorMsg": "کورتە ڕێگاکان نەتوانرا پاشەکەوت بکرێن، تکایە دووبارە هەوڵبدەرەوە"
|
|
||||||
},
|
|
||||||
"mobile": {
|
"mobile": {
|
||||||
"personalInfo": "زانیاری کەسی",
|
"personalInfo": "زانیاری کەسی",
|
||||||
"username": "ناوی بەکارهێنەر",
|
"username": "ناوی بەکارهێنەر",
|
||||||
@ -511,6 +500,17 @@
|
|||||||
"selectLayout": "نەخشە هەڵبژێرە",
|
"selectLayout": "نەخشە هەڵبژێرە",
|
||||||
"selectStartingDay": "ڕۆژی دەستپێکردنەکەت هەڵبژێرە",
|
"selectStartingDay": "ڕۆژی دەستپێکردنەکەت هەڵبژێرە",
|
||||||
"version": "وەشان"
|
"version": "وەشان"
|
||||||
|
},
|
||||||
|
"shortcuts": {
|
||||||
|
"shortcutsLabel": "کورتە ڕێگاکان",
|
||||||
|
"command": "فەرمان",
|
||||||
|
"keyBinding": "کورتکراوەکانی تەختەکلیل",
|
||||||
|
"addNewCommand": "زیاد کردنی فەرمانێکی نوێ",
|
||||||
|
"updateShortcutStep": "تێکەڵەی کلیلی دڵخواز داگرە و ENTER داگرە",
|
||||||
|
"shortcutIsAlreadyUsed": "ئەم کورتە ڕێگایە پێشتر بۆ: {conflict} بەکارهاتووە.",
|
||||||
|
"resetToDefault": "گەڕاندنەوە بۆ کلیلەکانی بنهڕهت",
|
||||||
|
"couldNotLoadErrorMsg": "کورتە ڕێگاکان نەتوانرا باربکرێن، تکایە دووبارە هەوڵبدەرەوە",
|
||||||
|
"couldNotSaveErrorMsg": "کورتە ڕێگاکان نەتوانرا پاشەکەوت بکرێن، تکایە دووبارە هەوڵبدەرەوە"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid": {
|
"grid": {
|
||||||
|
@ -382,17 +382,6 @@
|
|||||||
"pleaseInputYourStabilityAIKey": "Prosím vložte svůj Stability AI klíč",
|
"pleaseInputYourStabilityAIKey": "Prosím vložte svůj Stability AI klíč",
|
||||||
"clickToLogout": "Klin"
|
"clickToLogout": "Klin"
|
||||||
},
|
},
|
||||||
"shortcuts": {
|
|
||||||
"shortcutsLabel": "Klávesové zkratky",
|
|
||||||
"command": "Příkaz",
|
|
||||||
"keyBinding": "Přiřazená klávesa",
|
|
||||||
"addNewCommand": "Přidat nový příkaz",
|
|
||||||
"updateShortcutStep": "Stiskněte požadovanou kombinaci kláves a stiskněte ENTER",
|
|
||||||
"shortcutIsAlreadyUsed": "Tato zkratka je již použita pro: @@",
|
|
||||||
"resetToDefault": "Obnovit výchozí klávesové zkratky",
|
|
||||||
"couldNotLoadErrorMsg": "Nepodařilo se načíst klávesové zkratky, zkuste to znovu",
|
|
||||||
"couldNotSaveErrorMsg": "Nepodařilo seuložit klávesové zkta"
|
|
||||||
},
|
|
||||||
"mobile": {
|
"mobile": {
|
||||||
"personalInfo": "Osobní informace",
|
"personalInfo": "Osobní informace",
|
||||||
"username": "Uživatelské jméno",
|
"username": "Uživatelské jméno",
|
||||||
@ -405,6 +394,17 @@
|
|||||||
"userAgreement": "Uživatels",
|
"userAgreement": "Uživatels",
|
||||||
"userprofileError": "Nepodařilo se načíst uživatelský profil",
|
"userprofileError": "Nepodařilo se načíst uživatelský profil",
|
||||||
"userprofileErrorDescription": "Prosím zkuste se odhlásit a znovu přihlásit a zkontrolujte, zda problém přetrvává"
|
"userprofileErrorDescription": "Prosím zkuste se odhlásit a znovu přihlásit a zkontrolujte, zda problém přetrvává"
|
||||||
|
},
|
||||||
|
"shortcuts": {
|
||||||
|
"shortcutsLabel": "Klávesové zkratky",
|
||||||
|
"command": "Příkaz",
|
||||||
|
"keyBinding": "Přiřazená klávesa",
|
||||||
|
"addNewCommand": "Přidat nový příkaz",
|
||||||
|
"updateShortcutStep": "Stiskněte požadovanou kombinaci kláves a stiskněte ENTER",
|
||||||
|
"shortcutIsAlreadyUsed": "Tato zkratka je již použita pro: @@",
|
||||||
|
"resetToDefault": "Obnovit výchozí klávesové zkratky",
|
||||||
|
"couldNotLoadErrorMsg": "Nepodařilo se načíst klávesové zkratky, zkuste to znovu",
|
||||||
|
"couldNotSaveErrorMsg": "Nepodařilo seuložit klávesové zkta"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid": {
|
"grid": {
|
||||||
|
@ -149,8 +149,8 @@
|
|||||||
"newBoardText": "Neues Board",
|
"newBoardText": "Neues Board",
|
||||||
"chat": {
|
"chat": {
|
||||||
"newChat": "Neuer Chat",
|
"newChat": "Neuer Chat",
|
||||||
"inputMessageHint": "Nachricht an AppFlowy AI",
|
"inputMessageHint": "Nachricht an @:appName AI",
|
||||||
"unsupportedCloudPrompt": "Diese Funktion ist nur bei Verwendung der AppFlowy Cloud verfügbar",
|
"unsupportedCloudPrompt": "Diese Funktion ist nur bei Verwendung der @:appName Cloud verfügbar",
|
||||||
"relatedQuestion": "Verwandt",
|
"relatedQuestion": "Verwandt",
|
||||||
"serverUnavailable": "Dienst vorübergehend nicht verfügbar. Bitte versuche es später erneut.",
|
"serverUnavailable": "Dienst vorübergehend nicht verfügbar. Bitte versuche es später erneut.",
|
||||||
"aiServerUnavailable": "Beim Generieren einer Antwort ist ein Fehler aufgetreten.",
|
"aiServerUnavailable": "Beim Generieren einer Antwort ist ein Fehler aufgetreten.",
|
||||||
@ -279,7 +279,7 @@
|
|||||||
"Spaces": "Gemeinsam genutzte Bereiche",
|
"Spaces": "Gemeinsam genutzte Bereiche",
|
||||||
"public": "Öffentlich",
|
"public": "Öffentlich",
|
||||||
"clickToHidePublic": "Hier klicken, um den öffentlichen Bereich auszublenden.\nHier erstellte Seiten sind für jedes Mitglied sichtbar.",
|
"clickToHidePublic": "Hier klicken, um den öffentlichen Bereich auszublenden.\nHier erstellte Seiten sind für jedes Mitglied sichtbar.",
|
||||||
"addAPageToPublic": "Eine Seite zum öffentlichen Bereich hinzufügen."
|
"addAPageToPublic": "Eine Seite zur öffentlichen Domäne hinzufügen."
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"export": {
|
"export": {
|
||||||
@ -375,6 +375,11 @@
|
|||||||
"change": "E-Mail ändern"
|
"change": "E-Mail ändern"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"login": {
|
||||||
|
"title": "Kontoanmeldung",
|
||||||
|
"loginLabel": "Anmeldung",
|
||||||
|
"logoutLabel": "Ausloggen"
|
||||||
|
},
|
||||||
"keys": {
|
"keys": {
|
||||||
"title": "KI API-Schlüssel",
|
"title": "KI API-Schlüssel",
|
||||||
"openAILabel": "OpenAI API-Schlüssel",
|
"openAILabel": "OpenAI API-Schlüssel",
|
||||||
@ -384,11 +389,6 @@
|
|||||||
"stabilityAITooltip": "Der für die KI-Modelle zu verwendende Stability API-Schlüssel",
|
"stabilityAITooltip": "Der für die KI-Modelle zu verwendende Stability API-Schlüssel",
|
||||||
"stabilityAIHint": "Stability API-Schlüssel eingeben"
|
"stabilityAIHint": "Stability API-Schlüssel eingeben"
|
||||||
},
|
},
|
||||||
"login": {
|
|
||||||
"title": "Kontoanmeldung",
|
|
||||||
"loginLabel": "Anmeldung",
|
|
||||||
"logoutLabel": "Ausloggen"
|
|
||||||
},
|
|
||||||
"description": "Passe dein Profil an, verwalte deine Sicherheitseinstellungen und KI API-Schlüssel oder melde dich bei deinem Konto an."
|
"description": "Passe dein Profil an, verwalte deine Sicherheitseinstellungen und KI API-Schlüssel oder melde dich bei deinem Konto an."
|
||||||
},
|
},
|
||||||
"workspacePage": {
|
"workspacePage": {
|
||||||
@ -521,21 +521,22 @@
|
|||||||
},
|
},
|
||||||
"errorPage": {
|
"errorPage": {
|
||||||
"message": "Shortcuts konnten nicht geladen werden: {}",
|
"message": "Shortcuts konnten nicht geladen werden: {}",
|
||||||
"howToFix": "Bitte versuchen Sie es erneut. Wenn das Problem weiterhin besteht, melden Sie es bitte auf GitHub."
|
"howToFix": "Bitte versuche es erneut. Wenn das Problem weiterhin besteht, melde es bitte auf GitHub."
|
||||||
},
|
},
|
||||||
"resetDialog": {
|
"resetDialog": {
|
||||||
"title": "Shortcuts zurücksetzen",
|
"title": "Shortcuts zurücksetzen",
|
||||||
"description": "Dies wird alle Ihre Shortcuts auf die Standardeinstellungen zurücksetzen, dies kann nicht rückgängig gemacht werden, sind Sie sicher, dass Sie fortfahren möchten?",
|
"description": "Dies wird alle deine Shortcuts auf die Standardeinstellungen zurücksetzen, dies kann nicht rückgängig gemacht werden. Bist du dir sicher, dass du fortfahren möchtest?",
|
||||||
"buttonLabel": "Zurücksetzen"
|
"buttonLabel": "Zurücksetzen"
|
||||||
},
|
},
|
||||||
"conflictDialog": {
|
"conflictDialog": {
|
||||||
"title": "{} ist derzeit in Verwendung",
|
"title": "{} ist derzeit in Verwendung",
|
||||||
"descriptionPrefix": "Diese Tastenkombination wird derzeit verwendet von ",
|
"descriptionPrefix": "Diese Tastenkombination wird derzeit verwendet von ",
|
||||||
"descriptionSuffix": ". Wenn Sie diese Tastaturbelegung ersetzen, wird sie aus {} entfernt.",
|
"descriptionSuffix": ". Wenn du diese Tastaturbelegung ersetzt, wird sie aus {} entfernt.",
|
||||||
"confirmLabel": "Weiter"
|
"confirmLabel": "Weiter"
|
||||||
},
|
},
|
||||||
"editTooltip": "Zum Starten der Bearbeitung der Tastaturbelegung drücken.",
|
"editTooltip": "Zum Starten der Bearbeitung der Tastaturbelegung drücken.",
|
||||||
"keybindings": {
|
"keybindings": {
|
||||||
|
"toggleToDoList": "Aufgabenliste ein-/ausblenden",
|
||||||
"insertNewParagraphInCodeblock": "Neuen Absatz einfügen",
|
"insertNewParagraphInCodeblock": "Neuen Absatz einfügen",
|
||||||
"pasteInCodeblock": "In Codeblock einfügen",
|
"pasteInCodeblock": "In Codeblock einfügen",
|
||||||
"selectAllCodeblock": "Alles auswählen",
|
"selectAllCodeblock": "Alles auswählen",
|
||||||
@ -567,26 +568,146 @@
|
|||||||
"moveCursorEnd": "Cursor an das Zeilenende bewegen",
|
"moveCursorEnd": "Cursor an das Zeilenende bewegen",
|
||||||
"moveCursorRightWord": "Cursor ein Wort nach rechts bewegen",
|
"moveCursorRightWord": "Cursor ein Wort nach rechts bewegen",
|
||||||
"moveCursorRightSelect": "Auswählen und Cursor nach rechts bewegen",
|
"moveCursorRightSelect": "Auswählen und Cursor nach rechts bewegen",
|
||||||
"moveCursorEndSelect": "Auswählen und Cursor an das Zeilenende bewegen"
|
"moveCursorEndSelect": "Auswählen und Cursor an das Zeilenende bewegen",
|
||||||
|
"moveCursorRightWordSelect": "Markiere das Wort und bewege den Cursor ein Wort nach rechts",
|
||||||
|
"moveCursorUp": "Cursor nach oben bewegen",
|
||||||
|
"moveCursorTopSelect": "Auswählen und Cursor zum Anfang bewegen",
|
||||||
|
"moveCursorTop": "Cursor zum Anfang bewegen",
|
||||||
|
"moveCursorUpSelect": "Auswählen und Cursor nach oben bewegen",
|
||||||
|
"moveCursorBottomSelect": "Auswählen und Cursor ans Ende bewegen",
|
||||||
|
"moveCursorBottom": "Cursor ans Ende bewegen",
|
||||||
|
"moveCursorDown": "Cursor nach unten bewegen",
|
||||||
|
"moveCursorDownSelect": "Auswählen und Cursor nach unten bewegen",
|
||||||
|
"home": "Zum Anfang scrollen",
|
||||||
|
"end": "Zum Ende scrollen",
|
||||||
|
"toggleBold": "Fett ein-/ausschalten",
|
||||||
|
"toggleItalic": "Kursivschrift ein-/ausschalten",
|
||||||
|
"toggleUnderline": "Unterstreichung ein-/ausschalten",
|
||||||
|
"toggleStrikethrough": "Durchgestrichen ein-/ausschalten",
|
||||||
|
"toggleCode": "Inline-Code ein-/ausschalten",
|
||||||
|
"toggleHighlight": "Hervorhebung ein-/ausschalten",
|
||||||
|
"showLinkMenu": "Linkmenü anzeigen",
|
||||||
|
"openInlineLink": "Inline-Link öffnen",
|
||||||
|
"openLinks": "Alle ausgewählten Links öffnen",
|
||||||
|
"indent": "Einzug",
|
||||||
|
"outdent": "Ausrücken",
|
||||||
|
"exit": "Bearbeitung beenden",
|
||||||
|
"pageUp": "Eine Seite nach oben scrollen",
|
||||||
|
"pageDown": "Eine Seite nach unten scrollen",
|
||||||
|
"selectAll": "Alles auswählen",
|
||||||
|
"pasteWithoutFormatting": "Inhalt ohne Formatierung einfügen",
|
||||||
|
"showEmojiPicker": "Emoji-Auswahl anzeigen",
|
||||||
|
"enterInTableCell": "Zeilenumbruch in Tabelle hinzufügen",
|
||||||
|
"leftInTableCell": "In der Tabelle eine Zelle nach links verschieben",
|
||||||
|
"rightInTableCell": "In der Tabelle eine Zelle nach rechts verschieben",
|
||||||
|
"upInTableCell": "In der Tabelle eine Zelle nach oben verschieben",
|
||||||
|
"downInTableCell": "In der Tabelle eine Zelle nach unten verschieben",
|
||||||
|
"tabInTableCell": "Zur nächsten verfügbaren Zelle in der Tabelle gehen",
|
||||||
|
"shiftTabInTableCell": "Zur zuvor verfügbaren Zelle in der Tabelle gehen",
|
||||||
|
"backSpaceInTableCell": "Am Anfang der Zelle anhalten"
|
||||||
},
|
},
|
||||||
"commands": {
|
"commands": {
|
||||||
|
"codeBlockNewParagraph": "Füge einen neuen Absatz neben dem Codeblock ein",
|
||||||
|
"codeBlockIndentLines": "Füge am Zeilenanfang im Codeblock zwei Leerzeichen ein",
|
||||||
|
"codeBlockOutdentLines": "Lösche zwei Leerzeichen am Zeilenanfang im Codeblock",
|
||||||
"codeBlockAddTwoSpaces": "Einfügen von zwei Leerzeichen an der Cursorposition im Codeblock",
|
"codeBlockAddTwoSpaces": "Einfügen von zwei Leerzeichen an der Cursorposition im Codeblock",
|
||||||
|
"codeBlockSelectAll": "Wähle den gesamten Inhalt innerhalb eines Codeblocks aus",
|
||||||
"codeBlockPasteText": "Text in Codeblock einfügen",
|
"codeBlockPasteText": "Text in Codeblock einfügen",
|
||||||
"textAlignLeft": "Text nach links ausrichten",
|
"textAlignLeft": "Text nach links ausrichten",
|
||||||
"textAlignCenter": "Text nach rechts ausrichten"
|
"textAlignCenter": "Text nach rechts ausrichten",
|
||||||
|
"textAlignRight": "Text rechtsbündig ausrichten"
|
||||||
},
|
},
|
||||||
"couldNotLoadErrorMsg": "Konnte keine Shortcuts laden, versuchen Sie es erneut",
|
"couldNotLoadErrorMsg": "Konnte keine Shortcuts laden, versuche es erneut",
|
||||||
"couldNotSaveErrorMsg": "Shortcuts konnten nicht gespeichert werden, versuchen Sie es erneut"
|
"couldNotSaveErrorMsg": "Shortcuts konnten nicht gespeichert werden, versuche es erneut"
|
||||||
|
},
|
||||||
|
"aiPage": {
|
||||||
|
"title": "KI-Einstellungen",
|
||||||
|
"menuLabel": "KI-Einstellungen",
|
||||||
|
"keys": {
|
||||||
|
"enableAISearchTitle": "KI-Suche",
|
||||||
|
"aiSettingsDescription": "Wähle oder konfiguriere KI-Modelle, die in @:appName verwendet werden. Für eine optimale Leistung empfehlen wir die Verwendung der Standardmodelloptionen",
|
||||||
|
"loginToEnableAIFeature": "KI-Funktionen werden erst nach der Anmeldung bei @:appName Cloud aktiviert. Wenn du kein @:appName-Konto hast, gehe zu „Mein Konto“, um dich zu registrieren",
|
||||||
|
"llmModel": "Sprachmodell",
|
||||||
|
"title": "KI-API-Schlüssel",
|
||||||
|
"openAILabel": "OpenAI API-Schlüssel",
|
||||||
|
"openAITooltip": "Du findest deinen geheimen API-Schlüssel auf der API-Schlüsselseite",
|
||||||
|
"openAIHint": "Gebe deinen OpenAI API-Schlüssel ein",
|
||||||
|
"stabilityAILabel": "Stability API-Schlüssel",
|
||||||
|
"stabilityAITooltip": "Dein Stability API-Schlüssel, der zur Authentifizierung deiner Anfragen verwendet wird",
|
||||||
|
"stabilityAIHint": "Gebe deinen Stability API-Schlüssel ein"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"planPage": {
|
"planPage": {
|
||||||
"menuLabel": "Plan",
|
"menuLabel": "Plan",
|
||||||
|
"title": "Tarifplan",
|
||||||
"planUsage": {
|
"planUsage": {
|
||||||
|
"title": "Zusammenfassung der Plannutzung",
|
||||||
"storageLabel": "Speicher",
|
"storageLabel": "Speicher",
|
||||||
"storageUsage": "{} von {} GB"
|
"storageUsage": "{} von {} GB",
|
||||||
|
"collaboratorsLabel": "Gastmitarbeiter",
|
||||||
|
"collaboratorsUsage": "{} von {}",
|
||||||
|
"aiResponseLabel": "KI-Antworten",
|
||||||
|
"aiResponseUsage": "{} von {}",
|
||||||
|
"proBadge": "Pro",
|
||||||
|
"memberProToggle": "Unbegrenzte Mitgliederzahl",
|
||||||
|
"guestCollabToggle": "10 Gastmitarbeiter",
|
||||||
|
"aiCredit": {
|
||||||
|
"title": "@:appName KI-Guthaben hinzufügen",
|
||||||
|
"price": "5 $",
|
||||||
|
"priceDescription": "für 1.000 Credits",
|
||||||
|
"purchase": "Kauf von KI",
|
||||||
|
"info": "Füge 1.000 KI-Credits pro Arbeitsbereich hinzu und integriere anpassbare KI nahtlos in deinen Arbeitsablauf für intelligentere, schnellere Ergebnisse mit bis zu:",
|
||||||
|
"infoItemOne": "10.000 Antworten pro Datenbank",
|
||||||
|
"infoItemTwo": "1.000 Antworten pro Arbeitsbereich"
|
||||||
|
},
|
||||||
|
"currentPlan": {
|
||||||
|
"bannerLabel": "Derzeitiger Plan",
|
||||||
|
"freeTitle": "Kostenfrei",
|
||||||
|
"proTitle": "Pro",
|
||||||
|
"teamTitle": "Team",
|
||||||
|
"freeInfo": "Perfekt für Einzelpersonen oder kleine Teams mit bis zu 3 Mitgliedern.",
|
||||||
|
"proInfo": "Perfekt für kleine und mittlere Teams mit bis zu 10 Mitgliedern.",
|
||||||
|
"teamInfo": "Perfekt für alle produktiven und gut organisierten Teams.",
|
||||||
|
"upgrade": "Vergleichen &\n Upgraden",
|
||||||
|
"freeProOne": "Gemeinsamer Arbeitsbereich",
|
||||||
|
"freeProTwo": "Bis zu 3 Mitglieder (inkl. Eigentümer)",
|
||||||
|
"freeProThree": "Unbegrenzte Anzahl an Gästen (nur anzeigen)",
|
||||||
|
"freeProFour": "Speicher 5 GB",
|
||||||
|
"freeProFive": "30 Tage Änderungshistorie",
|
||||||
|
"freeConOne": "Gastmitarbeiter (Bearbeitungszugriff)",
|
||||||
|
"freeConTwo": "Unbegrenzter Speicherplatz",
|
||||||
|
"freeConThree": "6 Monate Änderungshistorie",
|
||||||
|
"professionalProOne": "Gemeinsamer Arbeitsbereich",
|
||||||
|
"professionalProTwo": "Unbegrenzte Mitgliederzahl",
|
||||||
|
"professionalProThree": "Unbegrenzte Anzahl an Gästen (nur anzeigen)",
|
||||||
|
"professionalProFour": "Unbegrenzter Speicherplatz",
|
||||||
|
"professionalProFive": "6 Monate Änderungshistorie",
|
||||||
|
"professionalConOne": "Unbegrenzte Anzahl an Gastmitarbeitern (Bearbeitungszugriff)",
|
||||||
|
"professionalConTwo": "Unbegrenzte KI-Antworten",
|
||||||
|
"professionalConThree": "1 Jahr Änderungshistorie",
|
||||||
|
"canceledInfo": "Dein Plan wurde gekündigt und du wirst am {} auf den kostenlosen Plan herabgestuft."
|
||||||
|
},
|
||||||
|
"deal": {
|
||||||
|
"bannerLabel": "Neujahrsangebot!",
|
||||||
|
"title": "Erweiter dein Team!",
|
||||||
|
"info": "Upgraden und 10 % auf Pro- und Team-Pläne sparen! Steiger die Produktivität deines Arbeitsplatzes mit leistungsstarken neuen Funktionen, einschließlich @:appName KI.",
|
||||||
|
"viewPlans": "Pläne anzeigen"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"billingPage": {
|
"billingPage": {
|
||||||
|
"menuLabel": "Abrechnung",
|
||||||
|
"title": "Abrechnung",
|
||||||
|
"plan": {
|
||||||
|
"title": "Plan",
|
||||||
|
"freeLabel": "Kostenfrei",
|
||||||
|
"proLabel": "Pro",
|
||||||
|
"planButtonLabel": "Plan ändern",
|
||||||
|
"billingPeriod": "Abrechnungszeitraum",
|
||||||
|
"periodButtonLabel": "Zeitraum bearbeiten"
|
||||||
|
},
|
||||||
"paymentDetails": {
|
"paymentDetails": {
|
||||||
|
"title": "Zahlungsdetails",
|
||||||
"methodLabel": "Zahlungsmethode",
|
"methodLabel": "Zahlungsmethode",
|
||||||
"methodButtonLabel": "Zahlungsmethode bearbeiten"
|
"methodButtonLabel": "Zahlungsmethode bearbeiten"
|
||||||
}
|
}
|
||||||
@ -598,7 +719,7 @@
|
|||||||
"actions": {
|
"actions": {
|
||||||
"upgrade": "Upgrade",
|
"upgrade": "Upgrade",
|
||||||
"downgrade": "Downgrade",
|
"downgrade": "Downgrade",
|
||||||
"downgradeDisabledTooltip": "Sie werden am Ende des Abrechnungszeitraums automatisch downgegradet",
|
"downgradeDisabledTooltip": "Du wirst am Ende des Abrechnungszeitraums automatisch herabgestuft",
|
||||||
"current": "Aktuell"
|
"current": "Aktuell"
|
||||||
},
|
},
|
||||||
"freePlan": {
|
"freePlan": {
|
||||||
@ -609,6 +730,7 @@
|
|||||||
},
|
},
|
||||||
"proPlan": {
|
"proPlan": {
|
||||||
"title": "Professionell",
|
"title": "Professionell",
|
||||||
|
"description": "Ein Ort für kleine Gruppen zum Planen und Organisieren.",
|
||||||
"price": "$10 /Monat",
|
"price": "$10 /Monat",
|
||||||
"priceInfo": "jährlich abgerechnet"
|
"priceInfo": "jährlich abgerechnet"
|
||||||
},
|
},
|
||||||
@ -644,12 +766,12 @@
|
|||||||
"itemEight": "10.000 monatlich"
|
"itemEight": "10.000 monatlich"
|
||||||
},
|
},
|
||||||
"paymentSuccess": {
|
"paymentSuccess": {
|
||||||
"title": "Sie sind jetzt im {} Plan!",
|
"title": "Du bist jetzt im {} Plan!",
|
||||||
"description": "Ihre Zahlung wurde erfolgreich verarbeitet und Ihr Plan wurde auf AppFlowy {} aktualisiert. Sie können die Details Ihres Plans auf der Seite \"Plan\" einsehen"
|
"description": "Deine Zahlung wurde erfolgreich verarbeitet und dein Plan wurde auf @:appName {} aktualisiert. Du kannst die Details deines Plans auf der Seite \"Plan\" einsehen"
|
||||||
},
|
},
|
||||||
"downgradeDialog": {
|
"downgradeDialog": {
|
||||||
"title": "Sind Sie sicher, dass Sie Ihren Plan downgraden wollen?",
|
"title": "Bist du sicher, dass du deinen Plan herabstufen willst?",
|
||||||
"description": "Wenn Sie Ihren Plan herabstufen, kehren Sie zum kostenlosen Plan zurück. Mitglieder können den Zugang zu Arbeitsbereichen verlieren und Sie müssen möglicherweise Speicherplatz freigeben, um die Speichergrenzen des kostenlosen Tarifs einzuhalten.",
|
"description": "Wenn du deinen Plan herabstufst, kehrst du zum kostenfreien Plan zurück. Mitglieder können den Zugang zu Arbeitsbereichen verlieren und du musst möglicherweise Speicherplatz freigeben, um die Speichergrenzen des kostenfreien Tarifs einzuhalten.",
|
||||||
"downgradeLabel": "Downgrade Plan"
|
"downgradeLabel": "Downgrade Plan"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -664,7 +786,7 @@
|
|||||||
"notifications": "Benachrichtigungen",
|
"notifications": "Benachrichtigungen",
|
||||||
"open": "Einstellungen öffnen",
|
"open": "Einstellungen öffnen",
|
||||||
"logout": "Abmelden",
|
"logout": "Abmelden",
|
||||||
"logoutPrompt": "Wollen sie sich wirklich Abmelden?",
|
"logoutPrompt": "Willst du dich wirklich abmelden?",
|
||||||
"selfEncryptionLogoutPrompt": "Willst du dich wirklich Abmelden? Bitte stelle sicher, dass der Encryption Secret Code kopiert wurde.",
|
"selfEncryptionLogoutPrompt": "Willst du dich wirklich Abmelden? Bitte stelle sicher, dass der Encryption Secret Code kopiert wurde.",
|
||||||
"syncSetting": "Sync Einstellung",
|
"syncSetting": "Sync Einstellung",
|
||||||
"cloudSettings": "Cloud Einstellungen",
|
"cloudSettings": "Cloud Einstellungen",
|
||||||
@ -816,7 +938,7 @@
|
|||||||
"failedToAddMember": "Mitglied konnte nicht hinzugefügt werden!",
|
"failedToAddMember": "Mitglied konnte nicht hinzugefügt werden!",
|
||||||
"addMemberSuccess": "Mitglied erfolgreich hinzugefügt",
|
"addMemberSuccess": "Mitglied erfolgreich hinzugefügt",
|
||||||
"removeMember": "Mitglied entfernen",
|
"removeMember": "Mitglied entfernen",
|
||||||
"areYouSureToRemoveMember": "Möchten Sie dieses Mitglied wirklich entfernen?",
|
"areYouSureToRemoveMember": "Möchtest du dieses Mitglied wirklich entfernen?",
|
||||||
"inviteMemberSuccess": "Die Einladung wurde erfolgreich versendet",
|
"inviteMemberSuccess": "Die Einladung wurde erfolgreich versendet",
|
||||||
"failedToInviteMember": "Das Einladen des Mitglieds ist fehlgeschlagen"
|
"failedToInviteMember": "Das Einladen des Mitglieds ist fehlgeschlagen"
|
||||||
}
|
}
|
||||||
@ -828,7 +950,7 @@
|
|||||||
"doubleTapToCopy": "Zweimal tippen, um den Pfad zu kopieren",
|
"doubleTapToCopy": "Zweimal tippen, um den Pfad zu kopieren",
|
||||||
"restoreLocation": "@:appName-Standardpfad wiederherstellen",
|
"restoreLocation": "@:appName-Standardpfad wiederherstellen",
|
||||||
"customizeLocation": "Einen anderen Ordner öffnen",
|
"customizeLocation": "Einen anderen Ordner öffnen",
|
||||||
"restartApp": "Bitte starten Sie die App neu, damit die Änderungen wirksam werden.",
|
"restartApp": "Bitte starte die App neu, damit die Änderungen wirksam werden.",
|
||||||
"exportDatabase": "Datenbank exportieren",
|
"exportDatabase": "Datenbank exportieren",
|
||||||
"selectFiles": "Dateien auswählen, die exportiert werden sollen",
|
"selectFiles": "Dateien auswählen, die exportiert werden sollen",
|
||||||
"selectAll": "Alle auswählen",
|
"selectAll": "Alle auswählen",
|
||||||
@ -911,7 +1033,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid": {
|
"grid": {
|
||||||
"deleteView": "Möchten Sie diese Ansicht wirklich löschen?",
|
"deleteView": "Möchtest du diese Ansicht wirklich löschen?",
|
||||||
"createView": "Neu",
|
"createView": "Neu",
|
||||||
"title": {
|
"title": {
|
||||||
"placeholder": "Unbenannt"
|
"placeholder": "Unbenannt"
|
||||||
@ -1089,8 +1211,8 @@
|
|||||||
"cannotFindCreatableField": "Es konnte kein geeignetes Feld zum Sortieren gefunden werden",
|
"cannotFindCreatableField": "Es konnte kein geeignetes Feld zum Sortieren gefunden werden",
|
||||||
"deleteAllSorts": "Alle Sortierungen entfernen",
|
"deleteAllSorts": "Alle Sortierungen entfernen",
|
||||||
"addSort": "Sortierung hinzufügen",
|
"addSort": "Sortierung hinzufügen",
|
||||||
"removeSorting": "Möchten Sie die Sortierung entfernen?",
|
"removeSorting": "Möchtest du die Sortierung entfernen?",
|
||||||
"fieldInUse": "Sie sortieren bereits nach diesem Feld"
|
"fieldInUse": "Du sortierst bereits nach diesem Feld"
|
||||||
},
|
},
|
||||||
"row": {
|
"row": {
|
||||||
"duplicate": "Duplikat",
|
"duplicate": "Duplikat",
|
||||||
@ -1103,8 +1225,8 @@
|
|||||||
"action": "Aktion",
|
"action": "Aktion",
|
||||||
"add": "Klicken, um unten hinzuzufügen",
|
"add": "Klicken, um unten hinzuzufügen",
|
||||||
"drag": "Ziehen, um zu verschieben",
|
"drag": "Ziehen, um zu verschieben",
|
||||||
"deleteRowPrompt": "Sind Sie sicher, dass Sie diese Zeile löschen wollen? Diese Aktion kann nicht rückgängig gemacht werden",
|
"deleteRowPrompt": "Bist du sicher, dass du diese Zeile löschen willst? Diese Aktion kann nicht rückgängig gemacht werden",
|
||||||
"deleteCardPrompt": "Sind Sie sicher, dass Sie diese Karte löschen wollen? Diese Aktion kann nicht rückgängig gemacht werden",
|
"deleteCardPrompt": "Bist du sicher, dass du diese Karte löschen willst? Diese Aktion kann nicht rückgängig gemacht werden",
|
||||||
"dragAndClick": "Ziehen, um zu verschieben. Klicke, um das Menü zu öffnen",
|
"dragAndClick": "Ziehen, um zu verschieben. Klicke, um das Menü zu öffnen",
|
||||||
"insertRecordAbove": "Füge Datensatz oben ein",
|
"insertRecordAbove": "Füge Datensatz oben ein",
|
||||||
"insertRecordBelow": "Füge Datensatz unten ein",
|
"insertRecordBelow": "Füge Datensatz unten ein",
|
||||||
@ -1133,7 +1255,7 @@
|
|||||||
},
|
},
|
||||||
"checklist": {
|
"checklist": {
|
||||||
"taskHint": "Aufgbenbeschreibbung",
|
"taskHint": "Aufgbenbeschreibbung",
|
||||||
"addNew": "Fügen Sie einen Artikel hinzu",
|
"addNew": "Füge eine Aufgabe hinzu",
|
||||||
"submitNewTask": "Erstellen",
|
"submitNewTask": "Erstellen",
|
||||||
"hideComplete": "Blende abgeschlossene Aufgaben aus",
|
"hideComplete": "Blende abgeschlossene Aufgaben aus",
|
||||||
"showComplete": "Zeige alle Aufgaben"
|
"showComplete": "Zeige alle Aufgaben"
|
||||||
@ -1141,7 +1263,7 @@
|
|||||||
"url": {
|
"url": {
|
||||||
"launch": "Im Browser öffnen",
|
"launch": "Im Browser öffnen",
|
||||||
"copy": "Webadresse kopieren",
|
"copy": "Webadresse kopieren",
|
||||||
"textFieldHint": "Geben Sie eine URL ein",
|
"textFieldHint": "Gebe eine URL ein",
|
||||||
"copiedNotification": "In die Zwischenablage kopiert!"
|
"copiedNotification": "In die Zwischenablage kopiert!"
|
||||||
},
|
},
|
||||||
"relation": {
|
"relation": {
|
||||||
@ -1220,7 +1342,8 @@
|
|||||||
"smartEditCouldNotFetchResult": "Das Ergebnis konnte nicht von OpenAI abgerufen werden",
|
"smartEditCouldNotFetchResult": "Das Ergebnis konnte nicht von OpenAI abgerufen werden",
|
||||||
"smartEditCouldNotFetchKey": "Der OpenAI-Schlüssel konnte nicht abgerufen werden",
|
"smartEditCouldNotFetchKey": "Der OpenAI-Schlüssel konnte nicht abgerufen werden",
|
||||||
"smartEditDisabled": "OpenAI in den Einstellungen verbinden",
|
"smartEditDisabled": "OpenAI in den Einstellungen verbinden",
|
||||||
"discardResponse": "Möchten Sie die KI-Antworten verwerfen?",
|
"appflowyAIEditDisabled": "Melde dich an, um KI-Funktionen zu aktivieren",
|
||||||
|
"discardResponse": "Möchtest du die KI-Antworten verwerfen?",
|
||||||
"createInlineMathEquation": "Formel erstellen",
|
"createInlineMathEquation": "Formel erstellen",
|
||||||
"fonts": "Schriftarten",
|
"fonts": "Schriftarten",
|
||||||
"insertDate": "Datum einfügen",
|
"insertDate": "Datum einfügen",
|
||||||
@ -1254,7 +1377,7 @@
|
|||||||
"addIcon": "Symbol hinzufügen",
|
"addIcon": "Symbol hinzufügen",
|
||||||
"changeIcon": "Symbol wechseln",
|
"changeIcon": "Symbol wechseln",
|
||||||
"coverRemoveAlert": "Nach dem Löschen wird es aus dem Titelbild entfernt.",
|
"coverRemoveAlert": "Nach dem Löschen wird es aus dem Titelbild entfernt.",
|
||||||
"alertDialogConfirmation": "Sicher, dass Sie weitermachen wollen?"
|
"alertDialogConfirmation": "Sicher, dass du weitermachen willst?"
|
||||||
},
|
},
|
||||||
"mathEquation": {
|
"mathEquation": {
|
||||||
"name": "Mathematische Formel",
|
"name": "Mathematische Formel",
|
||||||
@ -1288,7 +1411,7 @@
|
|||||||
"convertToLink": "Konvertieren zum eingebetteten Link"
|
"convertToLink": "Konvertieren zum eingebetteten Link"
|
||||||
},
|
},
|
||||||
"outline": {
|
"outline": {
|
||||||
"addHeadingToCreateOutline": "Fügen Sie Überschriften hinzu, um ein Inhaltsverzeichnis zu erstellen.",
|
"addHeadingToCreateOutline": "Füge Überschriften hinzu, um ein Inhaltsverzeichnis zu erstellen.",
|
||||||
"noMatchHeadings": "Keine passenden Überschriften gefunden."
|
"noMatchHeadings": "Keine passenden Überschriften gefunden."
|
||||||
},
|
},
|
||||||
"table": {
|
"table": {
|
||||||
@ -1329,7 +1452,7 @@
|
|||||||
"placeholder": "Inhaltsverzeichnis"
|
"placeholder": "Inhaltsverzeichnis"
|
||||||
},
|
},
|
||||||
"textBlock": {
|
"textBlock": {
|
||||||
"placeholder": "Geben Sie „/“ für Inhaltsblöcke ein"
|
"placeholder": "Gebe „/“ für Inhaltsblöcke ein"
|
||||||
},
|
},
|
||||||
"title": {
|
"title": {
|
||||||
"placeholder": "Ohne Titel"
|
"placeholder": "Ohne Titel"
|
||||||
@ -1457,6 +1580,7 @@
|
|||||||
"ungroupedButtonTooltip": "Enthält Karten, die keiner Gruppe zugeordnet sind",
|
"ungroupedButtonTooltip": "Enthält Karten, die keiner Gruppe zugeordnet sind",
|
||||||
"ungroupedItemsTitle": "Klicke, um dem Board hinzuzufügen",
|
"ungroupedItemsTitle": "Klicke, um dem Board hinzuzufügen",
|
||||||
"groupBy": "Gruppiert nach",
|
"groupBy": "Gruppiert nach",
|
||||||
|
"groupCondition": "Gruppenbedingung",
|
||||||
"referencedBoardPrefix": "Sicht von",
|
"referencedBoardPrefix": "Sicht von",
|
||||||
"notesTooltip": "Notizen vorhanden",
|
"notesTooltip": "Notizen vorhanden",
|
||||||
"mobile": {
|
"mobile": {
|
||||||
@ -1511,7 +1635,7 @@
|
|||||||
"other": "{count} Ereignisse ohne Datum"
|
"other": "{count} Ereignisse ohne Datum"
|
||||||
},
|
},
|
||||||
"unscheduledEventsTitle": "Ungeplante Events",
|
"unscheduledEventsTitle": "Ungeplante Events",
|
||||||
"clickToAdd": "Klicken Sie, um es zum Kalender hinzuzufügen",
|
"clickToAdd": "Klicken zum hinzufügen im Kalender",
|
||||||
"name": "Kalendereinstellungen",
|
"name": "Kalendereinstellungen",
|
||||||
"clickToOpen": "Hier klicken, um den Eintrag zu öffnen"
|
"clickToOpen": "Hier klicken, um den Eintrag zu öffnen"
|
||||||
},
|
},
|
||||||
@ -1521,7 +1645,7 @@
|
|||||||
},
|
},
|
||||||
"errorDialog": {
|
"errorDialog": {
|
||||||
"title": "@:appName-Fehler",
|
"title": "@:appName-Fehler",
|
||||||
"howToFixFallback": "Wir entschuldigen uns für die Unannehmlichkeiten! Reiche auf unserer GitHub-Seite ein Problem ein, das Ihren Fehler beschreibt.",
|
"howToFixFallback": "Wir entschuldigen uns für die Unannehmlichkeiten! Reiche auf unserer GitHub-Seite ein Problem ein, das deinen Fehler beschreibt.",
|
||||||
"github": "Auf GitHub ansehen"
|
"github": "Auf GitHub ansehen"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
@ -1538,8 +1662,8 @@
|
|||||||
},
|
},
|
||||||
"unSupportBlock": "Die aktuelle Version unterstützt diesen Block nicht.",
|
"unSupportBlock": "Die aktuelle Version unterstützt diesen Block nicht.",
|
||||||
"views": {
|
"views": {
|
||||||
"deleteContentTitle": "Möchten Sie den {pageType} wirklich löschen?",
|
"deleteContentTitle": "Möchtest du den {pageType} wirklich löschen?",
|
||||||
"deleteContentCaption": "Wenn Sie diesen {pageType} löschen, können Sie ihn aus dem Papierkorb wiederherstellen."
|
"deleteContentCaption": "Wenn du diesen {pageType} löschst, kannst du ihn aus dem Papierkorb wiederherstellen."
|
||||||
},
|
},
|
||||||
"colors": {
|
"colors": {
|
||||||
"custom": "Individuell",
|
"custom": "Individuell",
|
||||||
@ -1674,7 +1798,7 @@
|
|||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"weAreSorry": "Das tut uns leid",
|
"weAreSorry": "Das tut uns leid",
|
||||||
"loadingViewError": "Wir haben Schwierigkeiten diese Ansicht zu laden. Bitte prüfe die Internetverbindung, lade die App neu und zögere Sie nicht, dass Team zu kontaktieren, falls das Problem weiterhin besteht."
|
"loadingViewError": "Wir haben Schwierigkeiten diese Ansicht zu laden. Bitte prüfe die Internetverbindung, lade die App neu und zögere nicht, das Team zu kontaktieren, falls das Problem weiterhin besteht."
|
||||||
},
|
},
|
||||||
"editor": {
|
"editor": {
|
||||||
"bold": "Fett",
|
"bold": "Fett",
|
||||||
@ -1904,37 +2028,39 @@
|
|||||||
"betaLabel": "BETA",
|
"betaLabel": "BETA",
|
||||||
"betaTooltip": "Wir unterstützen derzeit nur die Suche nach Seiten",
|
"betaTooltip": "Wir unterstützen derzeit nur die Suche nach Seiten",
|
||||||
"fromTrashHint": "Aus dem Mülleimer",
|
"fromTrashHint": "Aus dem Mülleimer",
|
||||||
"noResultsHint": "Wir haben nicht gefunden, wonach Sie gesucht haben. Versuchen Sie, nach einem anderen Begriff zu suchen.",
|
"noResultsHint": "Wir haben nicht gefunden, wonach du gesucht hast. Versuche nach einem anderen Begriff zu suchen.",
|
||||||
"clearSearchTooltip": "Suchfeld löschen"
|
"clearSearchTooltip": "Suchfeld löschen"
|
||||||
},
|
},
|
||||||
"space": {
|
"space": {
|
||||||
"delete": "Löschen",
|
"delete": "Löschen",
|
||||||
"deleteConfirmation": "Löschen:",
|
"deleteConfirmation": "Löschen:",
|
||||||
"deleteConfirmationDescription": "Alle Seiten innerhalb dieses Space werden gelöscht und in den Papierkorb verschoben.",
|
"deleteConfirmationDescription": "Alle Seiten innerhalb dieses Space werden gelöscht und in den Papierkorb verschoben.",
|
||||||
"rename": "Space umbennen",
|
"rename": "Domäne umbennen",
|
||||||
"changeIcon": "Symbol ändern",
|
"changeIcon": "Symbol ändern",
|
||||||
"manage": "Space verwalten",
|
"manage": "Domäne verwalten",
|
||||||
"addNewSpace": "Space erstellen",
|
"addNewSpace": "Domäne erstellen",
|
||||||
"collapseAllSubPages": "Alle Unterseiten einklappen",
|
"collapseAllSubPages": "Alle Unterseiten einklappen",
|
||||||
"createNewSpace": "Einen neuen Space schaffen",
|
"createNewSpace": "Eine neue Domäne erstellen",
|
||||||
"createSpaceDescription": "Erstellen Sie mehrere öffentliche und private Bereiche, um Ihre Arbeit besser zu organisieren.",
|
"createSpaceDescription": "Erstellen mehrere öffentliche und private Domänen, um deine Arbeit besser zu organisieren.",
|
||||||
"spaceName": "Space name",
|
"spaceName": "Name der Domäne",
|
||||||
"permission": "Berechtigung",
|
"permission": "Berechtigung",
|
||||||
"publicPermission": "Öffentlich",
|
"publicPermission": "Öffentlich",
|
||||||
"publicPermissionDescription": "Alle Mitglieder des Arbeitsbereichs mit Vollzugriff",
|
"publicPermissionDescription": "Alle Mitglieder des Arbeitsbereichs mit Vollzugriff",
|
||||||
"privatePermission": "Privat",
|
"privatePermission": "Privat",
|
||||||
"privatePermissionDescription": "Nur Sie haben Zugang zu diesem Space",
|
"privatePermissionDescription": "Nur du hast Zugang zu dieser Domäne",
|
||||||
"spaceIconBackground": "Hintergrundfarbe",
|
"spaceIconBackground": "Hintergrundfarbe",
|
||||||
"spaceIcon": "Symbol",
|
"spaceIcon": "Symbol",
|
||||||
"dangerZone": "Gefahrenzone",
|
"dangerZone": "Gefahrenzone",
|
||||||
"unableToDeleteLastSpace": "Der letzte Space kann nicht gelöscht werden",
|
"unableToDeleteLastSpace": "Die letzte Domäne kann nicht gelöscht werden",
|
||||||
"unableToDeleteSpaceNotCreatedByYou": "Von anderen erstellte Spaces können nicht gelöscht werden",
|
"unableToDeleteSpaceNotCreatedByYou": "Von anderen erstellte Domänen können nicht gelöscht werden",
|
||||||
"enableSpacesForYourWorkspace": "Spaces für Ihren Arbeitsbereich aktivieren",
|
"enableSpacesForYourWorkspace": "Domänen für deinen Arbeitsbereich aktivieren",
|
||||||
"title": "Spaces",
|
"title": "Domänen",
|
||||||
"defaultSpaceName": "Allgemein",
|
"defaultSpaceName": "Allgemein",
|
||||||
"upgradeSpaceTitle": "Spaces freigeben",
|
"upgradeSpaceTitle": "Domänen aktivieren",
|
||||||
"upgradeSpaceDescription": "Erstellen Sie mehrere öffentliche und private Spaces, um Ihren Arbeitsbereich besser zu organisieren.",
|
"upgradeSpaceDescription": "Erstelle mehrere öffentliche und private Domänen, um deinen Arbeitsbereich besser zu organisieren.",
|
||||||
"upgrade": "Update",
|
"upgrade": "Update",
|
||||||
"upgradeYourSpace": "Mehrere Spaces erstellen"
|
"upgradeYourSpace": "Mehrere Domänen erstellen",
|
||||||
|
"quicklySwitch": "Schnell zur nächsten Domäne wechseln",
|
||||||
|
"duplicate": "Domäne duplizieren"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -154,8 +154,8 @@
|
|||||||
"newBoardText": "New board",
|
"newBoardText": "New board",
|
||||||
"chat": {
|
"chat": {
|
||||||
"newChat": "AI Chat",
|
"newChat": "AI Chat",
|
||||||
"inputMessageHint": "Message AppFlowy AI",
|
"inputMessageHint": "Message @:appName AI",
|
||||||
"unsupportedCloudPrompt": "This feature is only available when using AppFlowy Cloud",
|
"unsupportedCloudPrompt": "This feature is only available when using @:appName Cloud",
|
||||||
"relatedQuestion": "Related",
|
"relatedQuestion": "Related",
|
||||||
"serverUnavailable": "Service Temporarily Unavailable. Please try again later.",
|
"serverUnavailable": "Service Temporarily Unavailable. Please try again later.",
|
||||||
"aiServerUnavailable": "🌈 Uh-oh! 🌈. A unicorn ate our response. Please retry!",
|
"aiServerUnavailable": "🌈 Uh-oh! 🌈. A unicorn ate our response. Please retry!",
|
||||||
@ -496,6 +496,11 @@
|
|||||||
"description": "Clearing the cache will cause images and fonts to be re-downloaded on load. This action will not remove or modify your data.",
|
"description": "Clearing the cache will cause images and fonts to be re-downloaded on load. This action will not remove or modify your data.",
|
||||||
"successHint": "Cache cleared!"
|
"successHint": "Cache cleared!"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"fixYourData": "Fix your data",
|
||||||
|
"fixButton": "Fix",
|
||||||
|
"fixYourDataDescription": "If you're experiencing issues with your data, you can try to fix it here."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"shortcutsPage": {
|
"shortcutsPage": {
|
||||||
@ -579,7 +584,7 @@
|
|||||||
"indent": "Indent",
|
"indent": "Indent",
|
||||||
"outdent": "Outdent",
|
"outdent": "Outdent",
|
||||||
"exit": "Exit editing",
|
"exit": "Exit editing",
|
||||||
"pageUp": "Scroll on page up",
|
"pageUp": "Scroll one page up",
|
||||||
"pageDown": "Scroll one page down",
|
"pageDown": "Scroll one page down",
|
||||||
"selectAll": "Select all",
|
"selectAll": "Select all",
|
||||||
"pasteWithoutFormatting": "Paste content without formatting",
|
"pasteWithoutFormatting": "Paste content without formatting",
|
||||||
@ -612,8 +617,8 @@
|
|||||||
"menuLabel": "AI Settings",
|
"menuLabel": "AI Settings",
|
||||||
"keys": {
|
"keys": {
|
||||||
"enableAISearchTitle": "AI Search",
|
"enableAISearchTitle": "AI Search",
|
||||||
"aiSettingsDescription": "Select or configure Ai models used on AppFlowy. For best performance we recommend using the default model options",
|
"aiSettingsDescription": "Select or configure Ai models used on @:appName. For best performance we recommend using the default model options",
|
||||||
"loginToEnableAIFeature": "AI features are only enabled after logging in with AppFlowy Cloud. If you don't have an AppFlowy account, go to 'My Account' to sign up",
|
"loginToEnableAIFeature": "AI features are only enabled after logging in with @:appName Cloud. If you don't have an @:appName account, go to 'My Account' to sign up",
|
||||||
"llmModel": "Language Model",
|
"llmModel": "Language Model",
|
||||||
"title": "AI API Keys",
|
"title": "AI API Keys",
|
||||||
"openAILabel": "OpenAI API key",
|
"openAILabel": "OpenAI API key",
|
||||||
@ -638,8 +643,9 @@
|
|||||||
"proBadge": "Pro",
|
"proBadge": "Pro",
|
||||||
"memberProToggle": "Unlimited members",
|
"memberProToggle": "Unlimited members",
|
||||||
"guestCollabToggle": "10 guest collaborators",
|
"guestCollabToggle": "10 guest collaborators",
|
||||||
|
"storageUnlimited": "Unlimited storage with your Pro Plan",
|
||||||
"aiCredit": {
|
"aiCredit": {
|
||||||
"title": "Add AppFlowy AI Credit",
|
"title": "Add @:appName AI Credit",
|
||||||
"price": "5$",
|
"price": "5$",
|
||||||
"priceDescription": "for 1,000 credits",
|
"priceDescription": "for 1,000 credits",
|
||||||
"purchase": "Purchase AI",
|
"purchase": "Purchase AI",
|
||||||
@ -659,7 +665,7 @@
|
|||||||
"freeProOne": "Collaborative workspace",
|
"freeProOne": "Collaborative workspace",
|
||||||
"freeProTwo": "Up to 3 members (incl. owner)",
|
"freeProTwo": "Up to 3 members (incl. owner)",
|
||||||
"freeProThree": "Unlimited guests (view-only)",
|
"freeProThree": "Unlimited guests (view-only)",
|
||||||
"freeProFour": "Storage 5gb",
|
"freeProFour": "Storage 5GB",
|
||||||
"freeProFive": "30 day revision history",
|
"freeProFive": "30 day revision history",
|
||||||
"freeConOne": "Guest collaborators (edit access)",
|
"freeConOne": "Guest collaborators (edit access)",
|
||||||
"freeConTwo": "Unlimited storage",
|
"freeConTwo": "Unlimited storage",
|
||||||
@ -677,7 +683,7 @@
|
|||||||
"deal": {
|
"deal": {
|
||||||
"bannerLabel": "New year deal!",
|
"bannerLabel": "New year deal!",
|
||||||
"title": "Grow your team!",
|
"title": "Grow your team!",
|
||||||
"info": "Upgrade and save 10% off Pro and Team plans! Boost your workspace productivity with powerful new features including Appflowy Ai.",
|
"info": "Upgrade and save 10% off Pro and Team plans! Boost your workspace productivity with powerful new features including @:appName AI.",
|
||||||
"viewPlans": "View plans"
|
"viewPlans": "View plans"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -756,7 +762,7 @@
|
|||||||
},
|
},
|
||||||
"paymentSuccess": {
|
"paymentSuccess": {
|
||||||
"title": "You are now on the {} plan!",
|
"title": "You are now on the {} plan!",
|
||||||
"description": "Your payment has been successfully processed and your plan is upgraded to AppFlowy {}. You can view your plan details on the Plan page"
|
"description": "Your payment has been successfully processed and your plan is upgraded to @:appName {}. You can view your plan details on the Plan page"
|
||||||
},
|
},
|
||||||
"downgradeDialog": {
|
"downgradeDialog": {
|
||||||
"title": "Are you sure you want to downgrade your plan?",
|
"title": "Are you sure you want to downgrade your plan?",
|
||||||
@ -2033,4 +2039,4 @@
|
|||||||
"reportPage": "Report page",
|
"reportPage": "Report page",
|
||||||
"databaseHasNotBeenPublished": "This database hasn't been published yet"
|
"databaseHasNotBeenPublished": "This database hasn't been published yet"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -320,7 +320,6 @@
|
|||||||
"accountPage": {
|
"accountPage": {
|
||||||
"menuLabel": "Mi cuenta",
|
"menuLabel": "Mi cuenta",
|
||||||
"title": "Mi cuenta",
|
"title": "Mi cuenta",
|
||||||
"description": "Personaliza tu perfil, administra la seguridad de la cuenta y las claves API de IA, o inicia sesión en tu cuenta.",
|
|
||||||
"general": {
|
"general": {
|
||||||
"title": "Nombre de cuenta e imagen de perfil",
|
"title": "Nombre de cuenta e imagen de perfil",
|
||||||
"changeProfilePicture": "Cambiar"
|
"changeProfilePicture": "Cambiar"
|
||||||
@ -331,6 +330,11 @@
|
|||||||
"change": "Cambiar email"
|
"change": "Cambiar email"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"login": {
|
||||||
|
"title": "Inicio de sesión en la cuenta",
|
||||||
|
"loginLabel": "Inicio de sesión",
|
||||||
|
"logoutLabel": "Cerrar sesión"
|
||||||
|
},
|
||||||
"keys": {
|
"keys": {
|
||||||
"title": "Claves API de IA",
|
"title": "Claves API de IA",
|
||||||
"openAILabel": "Clave API de OpenAI",
|
"openAILabel": "Clave API de OpenAI",
|
||||||
@ -340,11 +344,7 @@
|
|||||||
"stabilityAITooltip": "La clave API de Stability que se utilizará en los modelos de IA",
|
"stabilityAITooltip": "La clave API de Stability que se utilizará en los modelos de IA",
|
||||||
"stabilityAIHint": "Ingresa tu clave API de Stability"
|
"stabilityAIHint": "Ingresa tu clave API de Stability"
|
||||||
},
|
},
|
||||||
"login": {
|
"description": "Personaliza tu perfil, administra la seguridad de la cuenta y las claves API de IA, o inicia sesión en tu cuenta."
|
||||||
"title": "Inicio de sesión en la cuenta",
|
|
||||||
"loginLabel": "Inicio de sesión",
|
|
||||||
"logoutLabel": "Cerrar sesión"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"menu": {
|
"menu": {
|
||||||
"appearance": "Apariencia",
|
"appearance": "Apariencia",
|
||||||
@ -555,6 +555,23 @@
|
|||||||
"pleaseInputYourStabilityAIKey": "por favor ingrese su clave de estabilidad AI",
|
"pleaseInputYourStabilityAIKey": "por favor ingrese su clave de estabilidad AI",
|
||||||
"clickToLogout": "Haga clic para cerrar la sesión del usuario actual."
|
"clickToLogout": "Haga clic para cerrar la sesión del usuario actual."
|
||||||
},
|
},
|
||||||
|
"mobile": {
|
||||||
|
"personalInfo": "Informacion personal",
|
||||||
|
"username": "Nombre de usuario",
|
||||||
|
"usernameEmptyError": "El nombre de usuario no puede estar vacío",
|
||||||
|
"about": "Acerca de",
|
||||||
|
"pushNotifications": "Notificaciones ",
|
||||||
|
"support": "Soporte",
|
||||||
|
"joinDiscord": "Únete a nosotros en Discord",
|
||||||
|
"privacyPolicy": "política de privacidad",
|
||||||
|
"userAgreement": "Acuerdo del Usuario",
|
||||||
|
"termsAndConditions": "Términos y condiciones",
|
||||||
|
"userprofileError": "No se pudo cargar el perfil de usuario",
|
||||||
|
"userprofileErrorDescription": "Intente cerrar sesión y volver a iniciarla para comprobar si el problema persiste.",
|
||||||
|
"selectLayout": "Seleccionar diseño",
|
||||||
|
"selectStartingDay": "Seleccione el día de inicio",
|
||||||
|
"version": "Versión"
|
||||||
|
},
|
||||||
"shortcuts": {
|
"shortcuts": {
|
||||||
"shortcutsLabel": "Atajos",
|
"shortcutsLabel": "Atajos",
|
||||||
"command": "Commando",
|
"command": "Commando",
|
||||||
@ -575,23 +592,6 @@
|
|||||||
"textAlignCenter": "Alinear el texto al centro",
|
"textAlignCenter": "Alinear el texto al centro",
|
||||||
"textAlignRight": "Alinear el texto a la derecha"
|
"textAlignRight": "Alinear el texto a la derecha"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"mobile": {
|
|
||||||
"personalInfo": "Informacion personal",
|
|
||||||
"username": "Nombre de usuario",
|
|
||||||
"usernameEmptyError": "El nombre de usuario no puede estar vacío",
|
|
||||||
"about": "Acerca de",
|
|
||||||
"pushNotifications": "Notificaciones ",
|
|
||||||
"support": "Soporte",
|
|
||||||
"joinDiscord": "Únete a nosotros en Discord",
|
|
||||||
"privacyPolicy": "política de privacidad",
|
|
||||||
"userAgreement": "Acuerdo del Usuario",
|
|
||||||
"termsAndConditions": "Términos y condiciones",
|
|
||||||
"userprofileError": "No se pudo cargar el perfil de usuario",
|
|
||||||
"userprofileErrorDescription": "Intente cerrar sesión y volver a iniciarla para comprobar si el problema persiste.",
|
|
||||||
"selectLayout": "Seleccionar diseño",
|
|
||||||
"selectStartingDay": "Seleccione el día de inicio",
|
|
||||||
"version": "Versión"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid": {
|
"grid": {
|
||||||
|
@ -432,17 +432,6 @@
|
|||||||
"pleaseInputYourStabilityAIKey": "Veuillez saisir votre clé de Stability AI",
|
"pleaseInputYourStabilityAIKey": "Veuillez saisir votre clé de Stability AI",
|
||||||
"clickToLogout": "Cliquez pour déconnecter l'utilisateur actuel"
|
"clickToLogout": "Cliquez pour déconnecter l'utilisateur actuel"
|
||||||
},
|
},
|
||||||
"shortcuts": {
|
|
||||||
"shortcutsLabel": "Raccourcis",
|
|
||||||
"command": "Commande",
|
|
||||||
"keyBinding": "Racourcis clavier",
|
|
||||||
"addNewCommand": "Ajouter une Nouvelle Commande",
|
|
||||||
"updateShortcutStep": "Appuyez sur la combinaison de touches souhaitée et appuyez sur ENTER",
|
|
||||||
"shortcutIsAlreadyUsed": "Ce raccourci est déjà utilisé pour : {conflict}",
|
|
||||||
"resetToDefault": "Réinitialiser les raccourcis clavier par défaut",
|
|
||||||
"couldNotLoadErrorMsg": "Impossible de charger les raccourcis, réessayez",
|
|
||||||
"couldNotSaveErrorMsg": "Impossible d'enregistrer les raccourcis. Réessayez"
|
|
||||||
},
|
|
||||||
"mobile": {
|
"mobile": {
|
||||||
"personalInfo": "Informations personnelles",
|
"personalInfo": "Informations personnelles",
|
||||||
"username": "Nom d'utilisateur",
|
"username": "Nom d'utilisateur",
|
||||||
@ -459,6 +448,17 @@
|
|||||||
"selectLayout": "Sélectionner la mise en page",
|
"selectLayout": "Sélectionner la mise en page",
|
||||||
"selectStartingDay": "Sélectionnez le jour de début",
|
"selectStartingDay": "Sélectionnez le jour de début",
|
||||||
"version": "Version"
|
"version": "Version"
|
||||||
|
},
|
||||||
|
"shortcuts": {
|
||||||
|
"shortcutsLabel": "Raccourcis",
|
||||||
|
"command": "Commande",
|
||||||
|
"keyBinding": "Racourcis clavier",
|
||||||
|
"addNewCommand": "Ajouter une Nouvelle Commande",
|
||||||
|
"updateShortcutStep": "Appuyez sur la combinaison de touches souhaitée et appuyez sur ENTER",
|
||||||
|
"shortcutIsAlreadyUsed": "Ce raccourci est déjà utilisé pour : {conflict}",
|
||||||
|
"resetToDefault": "Réinitialiser les raccourcis clavier par défaut",
|
||||||
|
"couldNotLoadErrorMsg": "Impossible de charger les raccourcis, réessayez",
|
||||||
|
"couldNotSaveErrorMsg": "Impossible d'enregistrer les raccourcis. Réessayez"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid": {
|
"grid": {
|
||||||
|
@ -622,6 +622,23 @@
|
|||||||
"pleaseInputYourStabilityAIKey": "Veuillez saisir votre clé de Stability AI",
|
"pleaseInputYourStabilityAIKey": "Veuillez saisir votre clé de Stability AI",
|
||||||
"clickToLogout": "Cliquez pour déconnecter l'utilisateur actuel"
|
"clickToLogout": "Cliquez pour déconnecter l'utilisateur actuel"
|
||||||
},
|
},
|
||||||
|
"mobile": {
|
||||||
|
"personalInfo": "Informations personnelles",
|
||||||
|
"username": "Nom d'utilisateur",
|
||||||
|
"usernameEmptyError": "Le nom d'utilisateur ne peut pas être vide",
|
||||||
|
"about": "À propos",
|
||||||
|
"pushNotifications": "Notifications push",
|
||||||
|
"support": "Support",
|
||||||
|
"joinDiscord": "Rejoignez-nous sur Discord",
|
||||||
|
"privacyPolicy": "Politique de Confidentialité",
|
||||||
|
"userAgreement": "Accord de l'utilisateur",
|
||||||
|
"termsAndConditions": "Termes et conditions",
|
||||||
|
"userprofileError": "Échec du chargement du profil utilisateur",
|
||||||
|
"userprofileErrorDescription": "Veuillez essayer de vous déconnecter et de vous reconnecter pour vérifier si le problème persiste.",
|
||||||
|
"selectLayout": "Sélectionner la mise en page",
|
||||||
|
"selectStartingDay": "Sélectionnez le jour de début",
|
||||||
|
"version": "Version"
|
||||||
|
},
|
||||||
"shortcuts": {
|
"shortcuts": {
|
||||||
"shortcutsLabel": "Raccourcis",
|
"shortcutsLabel": "Raccourcis",
|
||||||
"command": "Commande",
|
"command": "Commande",
|
||||||
@ -642,23 +659,6 @@
|
|||||||
"textAlignRight": "Aligner le texte à droite",
|
"textAlignRight": "Aligner le texte à droite",
|
||||||
"codeBlockDeleteTwoSpaces": "Supprimez deux espaces au début de la ligne dans le bloc de code"
|
"codeBlockDeleteTwoSpaces": "Supprimez deux espaces au début de la ligne dans le bloc de code"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"mobile": {
|
|
||||||
"personalInfo": "Informations personnelles",
|
|
||||||
"username": "Nom d'utilisateur",
|
|
||||||
"usernameEmptyError": "Le nom d'utilisateur ne peut pas être vide",
|
|
||||||
"about": "À propos",
|
|
||||||
"pushNotifications": "Notifications push",
|
|
||||||
"support": "Support",
|
|
||||||
"joinDiscord": "Rejoignez-nous sur Discord",
|
|
||||||
"privacyPolicy": "Politique de Confidentialité",
|
|
||||||
"userAgreement": "Accord de l'utilisateur",
|
|
||||||
"termsAndConditions": "Termes et conditions",
|
|
||||||
"userprofileError": "Échec du chargement du profil utilisateur",
|
|
||||||
"userprofileErrorDescription": "Veuillez essayer de vous déconnecter et de vous reconnecter pour vérifier si le problème persiste.",
|
|
||||||
"selectLayout": "Sélectionner la mise en page",
|
|
||||||
"selectStartingDay": "Sélectionnez le jour de début",
|
|
||||||
"version": "Version"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid": {
|
"grid": {
|
||||||
|
@ -380,17 +380,6 @@
|
|||||||
"pleaseInputYourStabilityAIKey": "Masukkan kunci Stability AI anda",
|
"pleaseInputYourStabilityAIKey": "Masukkan kunci Stability AI anda",
|
||||||
"clickToLogout": "Klik untuk keluar dari pengguna saat ini"
|
"clickToLogout": "Klik untuk keluar dari pengguna saat ini"
|
||||||
},
|
},
|
||||||
"shortcuts": {
|
|
||||||
"shortcutsLabel": "Pintasan",
|
|
||||||
"command": "Perintah",
|
|
||||||
"keyBinding": "Keybindin",
|
|
||||||
"addNewCommand": "Tambah Perintah Baru",
|
|
||||||
"updateShortcutStep": "Tekan kombinasi tombol yang diinginkan dan tekan ENTER",
|
|
||||||
"shortcutIsAlreadyUsed": "Pintasan ini sudah digunakan untuk: {conflict}",
|
|
||||||
"resetToDefault": "Mengatur ulang ke keybinding default",
|
|
||||||
"couldNotLoadErrorMsg": "Tidak dapat memuat pintasan, Coba lagi",
|
|
||||||
"couldNotSaveErrorMsg": "Tidak dapat menyimpan pintasan, Coba lagi"
|
|
||||||
},
|
|
||||||
"mobile": {
|
"mobile": {
|
||||||
"personalInfo": "Informasi pribadi",
|
"personalInfo": "Informasi pribadi",
|
||||||
"username": "Nama Pengguna",
|
"username": "Nama Pengguna",
|
||||||
@ -401,6 +390,17 @@
|
|||||||
"joinDiscord": "Bergabunglah dengan kami di Discord",
|
"joinDiscord": "Bergabunglah dengan kami di Discord",
|
||||||
"privacyPolicy": "Kebijakan Privasi",
|
"privacyPolicy": "Kebijakan Privasi",
|
||||||
"userAgreement": "Perjanjian Pengguna"
|
"userAgreement": "Perjanjian Pengguna"
|
||||||
|
},
|
||||||
|
"shortcuts": {
|
||||||
|
"shortcutsLabel": "Pintasan",
|
||||||
|
"command": "Perintah",
|
||||||
|
"keyBinding": "Keybindin",
|
||||||
|
"addNewCommand": "Tambah Perintah Baru",
|
||||||
|
"updateShortcutStep": "Tekan kombinasi tombol yang diinginkan dan tekan ENTER",
|
||||||
|
"shortcutIsAlreadyUsed": "Pintasan ini sudah digunakan untuk: {conflict}",
|
||||||
|
"resetToDefault": "Mengatur ulang ke keybinding default",
|
||||||
|
"couldNotLoadErrorMsg": "Tidak dapat memuat pintasan, Coba lagi",
|
||||||
|
"couldNotSaveErrorMsg": "Tidak dapat menyimpan pintasan, Coba lagi"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid": {
|
"grid": {
|
||||||
|
@ -431,17 +431,6 @@
|
|||||||
"pleaseInputYourStabilityAIKey": "per favore inserisci la tua chiave Stability AI",
|
"pleaseInputYourStabilityAIKey": "per favore inserisci la tua chiave Stability AI",
|
||||||
"clickToLogout": "Fare clic per disconnettere l'utente corrente"
|
"clickToLogout": "Fare clic per disconnettere l'utente corrente"
|
||||||
},
|
},
|
||||||
"shortcuts": {
|
|
||||||
"shortcutsLabel": "Scorciatoie",
|
|
||||||
"command": "Comando",
|
|
||||||
"keyBinding": "Combinazione",
|
|
||||||
"addNewCommand": "Aggiungi un nuovo comando",
|
|
||||||
"updateShortcutStep": "Premi la combinazione di tasti e poi premi INVIO",
|
|
||||||
"shortcutIsAlreadyUsed": "Questa scorciatoia è già usata per: {conflict}",
|
|
||||||
"resetToDefault": "Ripristina le combinazioni di default",
|
|
||||||
"couldNotLoadErrorMsg": "Impossibile caricare le scorciatoie, Riprova.",
|
|
||||||
"couldNotSaveErrorMsg": "Impossibile salvare le scorciatoie, Riprova."
|
|
||||||
},
|
|
||||||
"mobile": {
|
"mobile": {
|
||||||
"personalInfo": "Informazione personale",
|
"personalInfo": "Informazione personale",
|
||||||
"username": "Nome utente",
|
"username": "Nome utente",
|
||||||
@ -458,6 +447,17 @@
|
|||||||
"selectLayout": "Seleziona disposizione",
|
"selectLayout": "Seleziona disposizione",
|
||||||
"selectStartingDay": "Seleziona il giorno di inizio",
|
"selectStartingDay": "Seleziona il giorno di inizio",
|
||||||
"version": "Versione"
|
"version": "Versione"
|
||||||
|
},
|
||||||
|
"shortcuts": {
|
||||||
|
"shortcutsLabel": "Scorciatoie",
|
||||||
|
"command": "Comando",
|
||||||
|
"keyBinding": "Combinazione",
|
||||||
|
"addNewCommand": "Aggiungi un nuovo comando",
|
||||||
|
"updateShortcutStep": "Premi la combinazione di tasti e poi premi INVIO",
|
||||||
|
"shortcutIsAlreadyUsed": "Questa scorciatoia è già usata per: {conflict}",
|
||||||
|
"resetToDefault": "Ripristina le combinazioni di default",
|
||||||
|
"couldNotLoadErrorMsg": "Impossibile caricare le scorciatoie, Riprova.",
|
||||||
|
"couldNotSaveErrorMsg": "Impossibile salvare le scorciatoie, Riprova."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid": {
|
"grid": {
|
||||||
|
@ -345,13 +345,6 @@
|
|||||||
"selectAnIcon": "アイコンを選択してください",
|
"selectAnIcon": "アイコンを選択してください",
|
||||||
"pleaseInputYourOpenAIKey": "OpenAI キーを入力してください"
|
"pleaseInputYourOpenAIKey": "OpenAI キーを入力してください"
|
||||||
},
|
},
|
||||||
"shortcuts": {
|
|
||||||
"shortcutsLabel": "ショートカット",
|
|
||||||
"command": "コマンド",
|
|
||||||
"keyBinding": "キーバインディング",
|
|
||||||
"addNewCommand": "新しいコマンドを追加",
|
|
||||||
"resetToDefault": "キーバインディングをデフォルトに戻す"
|
|
||||||
},
|
|
||||||
"mobile": {
|
"mobile": {
|
||||||
"username": "ユーザー名",
|
"username": "ユーザー名",
|
||||||
"usernameEmptyError": "ユーザー名は空白にはできません",
|
"usernameEmptyError": "ユーザー名は空白にはできません",
|
||||||
@ -361,6 +354,13 @@
|
|||||||
"userAgreement": "ユーザー同意",
|
"userAgreement": "ユーザー同意",
|
||||||
"termsAndConditions": "利用規約",
|
"termsAndConditions": "利用規約",
|
||||||
"version": "バージョン"
|
"version": "バージョン"
|
||||||
|
},
|
||||||
|
"shortcuts": {
|
||||||
|
"shortcutsLabel": "ショートカット",
|
||||||
|
"command": "コマンド",
|
||||||
|
"keyBinding": "キーバインディング",
|
||||||
|
"addNewCommand": "新しいコマンドを追加",
|
||||||
|
"resetToDefault": "キーバインディングをデフォルトに戻す"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid": {
|
"grid": {
|
||||||
|
@ -425,6 +425,23 @@
|
|||||||
"pleaseInputYourStabilityAIKey": "insira sua chave Stability AI",
|
"pleaseInputYourStabilityAIKey": "insira sua chave Stability AI",
|
||||||
"clickToLogout": "Clique para sair do usuário atual"
|
"clickToLogout": "Clique para sair do usuário atual"
|
||||||
},
|
},
|
||||||
|
"mobile": {
|
||||||
|
"personalInfo": "Informações pessoais",
|
||||||
|
"username": "Nome de usuário",
|
||||||
|
"usernameEmptyError": "O nome de usuário não pode ficar vazio",
|
||||||
|
"about": "Sobre",
|
||||||
|
"pushNotifications": "Notificações via push",
|
||||||
|
"support": "Apoiar",
|
||||||
|
"joinDiscord": "Junte-se a nós no Discord",
|
||||||
|
"privacyPolicy": "Política de Privacidade",
|
||||||
|
"userAgreement": "Termo de Acordo do Usuário",
|
||||||
|
"termsAndConditions": "Termos e Condições",
|
||||||
|
"userprofileError": "Falha ao carregar o perfil do usuário",
|
||||||
|
"userprofileErrorDescription": "Tente sair e fazer login novamente para verificar se o problema ainda persiste.",
|
||||||
|
"selectLayout": "Selecione o layout",
|
||||||
|
"selectStartingDay": "Selecione o dia de início",
|
||||||
|
"version": "Versão"
|
||||||
|
},
|
||||||
"shortcuts": {
|
"shortcuts": {
|
||||||
"shortcutsLabel": "Atalhos",
|
"shortcutsLabel": "Atalhos",
|
||||||
"command": "Comando",
|
"command": "Comando",
|
||||||
@ -445,23 +462,6 @@
|
|||||||
"textAlignRight": "Alinhar texto à direita",
|
"textAlignRight": "Alinhar texto à direita",
|
||||||
"codeBlockDeleteTwoSpaces": "Bloco de código: excluir dois espaços no início da linha"
|
"codeBlockDeleteTwoSpaces": "Bloco de código: excluir dois espaços no início da linha"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"mobile": {
|
|
||||||
"personalInfo": "Informações pessoais",
|
|
||||||
"username": "Nome de usuário",
|
|
||||||
"usernameEmptyError": "O nome de usuário não pode ficar vazio",
|
|
||||||
"about": "Sobre",
|
|
||||||
"pushNotifications": "Notificações via push",
|
|
||||||
"support": "Apoiar",
|
|
||||||
"joinDiscord": "Junte-se a nós no Discord",
|
|
||||||
"privacyPolicy": "Política de Privacidade",
|
|
||||||
"userAgreement": "Termo de Acordo do Usuário",
|
|
||||||
"termsAndConditions": "Termos e Condições",
|
|
||||||
"userprofileError": "Falha ao carregar o perfil do usuário",
|
|
||||||
"userprofileErrorDescription": "Tente sair e fazer login novamente para verificar se o problema ainda persiste.",
|
|
||||||
"selectLayout": "Selecione o layout",
|
|
||||||
"selectStartingDay": "Selecione o dia de início",
|
|
||||||
"version": "Versão"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid": {
|
"grid": {
|
||||||
|
@ -443,17 +443,6 @@
|
|||||||
"pleaseInputYourStabilityAIKey": "Пожалуйста, введите свой токен Stability AI",
|
"pleaseInputYourStabilityAIKey": "Пожалуйста, введите свой токен Stability AI",
|
||||||
"clickToLogout": "Нажмите, чтобы выйти из текущего аккаунта"
|
"clickToLogout": "Нажмите, чтобы выйти из текущего аккаунта"
|
||||||
},
|
},
|
||||||
"shortcuts": {
|
|
||||||
"shortcutsLabel": "Горячие клавиши",
|
|
||||||
"command": "Команда",
|
|
||||||
"keyBinding": "Привязка клавиш",
|
|
||||||
"addNewCommand": "Добавить новую команду",
|
|
||||||
"updateShortcutStep": "Нажмите нужную комбинацию клавиш и нажмите Enter.",
|
|
||||||
"shortcutIsAlreadyUsed": "Это сочетание клавиш уже используется для: {conflict}",
|
|
||||||
"resetToDefault": "Сбросить к стандартным сочетаниям клавиш",
|
|
||||||
"couldNotLoadErrorMsg": "Не удалось загрузить горячие клавиши, попробуйте снова",
|
|
||||||
"couldNotSaveErrorMsg": "Не удалось сохранить горячие клавиши, попробуйте снова"
|
|
||||||
},
|
|
||||||
"mobile": {
|
"mobile": {
|
||||||
"personalInfo": "Личная информация",
|
"personalInfo": "Личная информация",
|
||||||
"username": "Имя пользователя",
|
"username": "Имя пользователя",
|
||||||
@ -470,6 +459,17 @@
|
|||||||
"selectLayout": "Выбрать раскладку",
|
"selectLayout": "Выбрать раскладку",
|
||||||
"selectStartingDay": "Выбрать день начала",
|
"selectStartingDay": "Выбрать день начала",
|
||||||
"version": "Версия"
|
"version": "Версия"
|
||||||
|
},
|
||||||
|
"shortcuts": {
|
||||||
|
"shortcutsLabel": "Горячие клавиши",
|
||||||
|
"command": "Команда",
|
||||||
|
"keyBinding": "Привязка клавиш",
|
||||||
|
"addNewCommand": "Добавить новую команду",
|
||||||
|
"updateShortcutStep": "Нажмите нужную комбинацию клавиш и нажмите Enter.",
|
||||||
|
"shortcutIsAlreadyUsed": "Это сочетание клавиш уже используется для: {conflict}",
|
||||||
|
"resetToDefault": "Сбросить к стандартным сочетаниям клавиш",
|
||||||
|
"couldNotLoadErrorMsg": "Не удалось загрузить горячие клавиши, попробуйте снова",
|
||||||
|
"couldNotSaveErrorMsg": "Не удалось сохранить горячие клавиши, попробуйте снова"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid": {
|
"grid": {
|
||||||
|
@ -332,12 +332,12 @@
|
|||||||
"change": "Email Değiş"
|
"change": "Email Değiş"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"keys": {
|
|
||||||
"openAIHint": "OpenAI API Anahtarını Gir"
|
|
||||||
},
|
|
||||||
"login": {
|
"login": {
|
||||||
"loginLabel": "Giriş Yap",
|
"loginLabel": "Giriş Yap",
|
||||||
"logoutLabel": "Çıkış Yap"
|
"logoutLabel": "Çıkış Yap"
|
||||||
|
},
|
||||||
|
"keys": {
|
||||||
|
"openAIHint": "OpenAI API Anahtarını Gir"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"workspacePage": {
|
"workspacePage": {
|
||||||
@ -557,6 +557,23 @@
|
|||||||
"pleaseInputYourStabilityAIKey": "Lütfen Stability AI anahtarınızı girin",
|
"pleaseInputYourStabilityAIKey": "Lütfen Stability AI anahtarınızı girin",
|
||||||
"clickToLogout": "Geçerli kullanıcıdan çıkış yapmak için tıklayın"
|
"clickToLogout": "Geçerli kullanıcıdan çıkış yapmak için tıklayın"
|
||||||
},
|
},
|
||||||
|
"mobile": {
|
||||||
|
"personalInfo": "Kişisel Bilgiler",
|
||||||
|
"username": "Kullanıcı Adı",
|
||||||
|
"usernameEmptyError": "Kullanıcı adı boş olamaz",
|
||||||
|
"about": "Hakkında",
|
||||||
|
"pushNotifications": "Anında Bildirimler",
|
||||||
|
"support": "Destek",
|
||||||
|
"joinDiscord": "Discord'da bize katılın",
|
||||||
|
"privacyPolicy": "Gizlilik Politikası",
|
||||||
|
"userAgreement": "Kullanıcı Sözleşmesi",
|
||||||
|
"termsAndConditions": "Şartlar ve Koşullar",
|
||||||
|
"userprofileError": "Kullanıcı profili yüklenemedi",
|
||||||
|
"userprofileErrorDescription": "Lütfen sorunun devam edip etmediğini kontrol etmek için çıkış yapıp tekrar giriş yapmayı deneyin.",
|
||||||
|
"selectLayout": "Düzen seçin",
|
||||||
|
"selectStartingDay": "Başlangıç gününü seçin",
|
||||||
|
"version": "Sürüm"
|
||||||
|
},
|
||||||
"shortcuts": {
|
"shortcuts": {
|
||||||
"shortcutsLabel": "Kısayollar",
|
"shortcutsLabel": "Kısayollar",
|
||||||
"command": "Komut",
|
"command": "Komut",
|
||||||
@ -579,23 +596,6 @@
|
|||||||
"textAlignRight": "Metni sağa hizala",
|
"textAlignRight": "Metni sağa hizala",
|
||||||
"codeBlockDeleteTwoSpaces": "Kod bloğunda satır başındaki iki boşluğu sil"
|
"codeBlockDeleteTwoSpaces": "Kod bloğunda satır başındaki iki boşluğu sil"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"mobile": {
|
|
||||||
"personalInfo": "Kişisel Bilgiler",
|
|
||||||
"username": "Kullanıcı Adı",
|
|
||||||
"usernameEmptyError": "Kullanıcı adı boş olamaz",
|
|
||||||
"about": "Hakkında",
|
|
||||||
"pushNotifications": "Anında Bildirimler",
|
|
||||||
"support": "Destek",
|
|
||||||
"joinDiscord": "Discord'da bize katılın",
|
|
||||||
"privacyPolicy": "Gizlilik Politikası",
|
|
||||||
"userAgreement": "Kullanıcı Sözleşmesi",
|
|
||||||
"termsAndConditions": "Şartlar ve Koşullar",
|
|
||||||
"userprofileError": "Kullanıcı profili yüklenemedi",
|
|
||||||
"userprofileErrorDescription": "Lütfen sorunun devam edip etmediğini kontrol etmek için çıkış yapıp tekrar giriş yapmayı deneyin.",
|
|
||||||
"selectLayout": "Düzen seçin",
|
|
||||||
"selectStartingDay": "Başlangıç gününü seçin",
|
|
||||||
"version": "Sürüm"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid": {
|
"grid": {
|
||||||
|
@ -284,7 +284,7 @@
|
|||||||
"themeUpload": {
|
"themeUpload": {
|
||||||
"button": "Завантажити",
|
"button": "Завантажити",
|
||||||
"uploadTheme": "Завантажити тему",
|
"uploadTheme": "Завантажити тему",
|
||||||
"description": "Завантажте свою власну тему AppFlowy, скориставшись кнопкою нижче.",
|
"description": "Завантажте свою власну тему @:appName, скориставшись кнопкою нижче.",
|
||||||
"loading": "Будь ласка, зачекайте, поки ми перевіряємо та завантажуємо вашу тему...",
|
"loading": "Будь ласка, зачекайте, поки ми перевіряємо та завантажуємо вашу тему...",
|
||||||
"uploadSuccess": "Вашу тему успішно завантажено",
|
"uploadSuccess": "Вашу тему успішно завантажено",
|
||||||
"deletionFailure": "Не вдалося видалити тему. Спробуйте видалити її вручну.",
|
"deletionFailure": "Не вдалося видалити тему. Спробуйте видалити її вручну.",
|
||||||
@ -315,7 +315,7 @@
|
|||||||
"defaultLocation": "Де зараз зберігаються ваші дані",
|
"defaultLocation": "Де зараз зберігаються ваші дані",
|
||||||
"exportData": "Експортуйте свої дані",
|
"exportData": "Експортуйте свої дані",
|
||||||
"doubleTapToCopy": "Подвійний натиск для копіювання шляху",
|
"doubleTapToCopy": "Подвійний натиск для копіювання шляху",
|
||||||
"restoreLocation": "Відновити до шляху за замовчуванням AppFlowy",
|
"restoreLocation": "Відновити до шляху за замовчуванням @:appName",
|
||||||
"customizeLocation": "Відкрити іншу папку",
|
"customizeLocation": "Відкрити іншу папку",
|
||||||
"restartApp": "Будь ласка, перезапустіть програму для врахування змін.",
|
"restartApp": "Будь ласка, перезапустіть програму для врахування змін.",
|
||||||
"exportDatabase": "Експорт бази даних",
|
"exportDatabase": "Експорт бази даних",
|
||||||
@ -327,10 +327,10 @@
|
|||||||
"defineWhereYourDataIsStored": "Визначте, де зберігаються ваші дані",
|
"defineWhereYourDataIsStored": "Визначте, де зберігаються ваші дані",
|
||||||
"open": "Відкрити",
|
"open": "Відкрити",
|
||||||
"openFolder": "Відкрити існуючу папку",
|
"openFolder": "Відкрити існуючу папку",
|
||||||
"openFolderDesc": "Читати та записувати в вашу існуючу папку AppFlowy",
|
"openFolderDesc": "Читати та записувати в вашу існуючу папку @:appName",
|
||||||
"folderHintText": "ім'я папки",
|
"folderHintText": "ім'я папки",
|
||||||
"location": "Створення нової папки",
|
"location": "Створення нової папки",
|
||||||
"locationDesc": "Оберіть ім'я для папки з даними AppFlowy",
|
"locationDesc": "Оберіть ім'я для папки з даними @:appName",
|
||||||
"browser": "Перегляд",
|
"browser": "Перегляд",
|
||||||
"create": "Створити",
|
"create": "Створити",
|
||||||
"set": "Встановити",
|
"set": "Встановити",
|
||||||
@ -341,7 +341,7 @@
|
|||||||
"change": "Змінити",
|
"change": "Змінити",
|
||||||
"openLocationTooltips": "Відкрити інший каталог даних",
|
"openLocationTooltips": "Відкрити інший каталог даних",
|
||||||
"openCurrentDataFolder": "Відкрити поточний каталог даних",
|
"openCurrentDataFolder": "Відкрити поточний каталог даних",
|
||||||
"recoverLocationTooltips": "Скинути до каталогу даних за замовчуванням AppFlowy",
|
"recoverLocationTooltips": "Скинути до каталогу даних за замовчуванням @:appName",
|
||||||
"exportFileSuccess": "Файл успішно експортовано!",
|
"exportFileSuccess": "Файл успішно експортовано!",
|
||||||
"exportFileFail": "Помилка експорту файлу!",
|
"exportFileFail": "Помилка експорту файлу!",
|
||||||
"export": "Експорт"
|
"export": "Експорт"
|
||||||
@ -720,7 +720,7 @@
|
|||||||
"referencedCalendarPrefix": "Вид на"
|
"referencedCalendarPrefix": "Вид на"
|
||||||
},
|
},
|
||||||
"errorDialog": {
|
"errorDialog": {
|
||||||
"title": "Помилка в AppFlowy",
|
"title": "Помилка в @:appName",
|
||||||
"howToFixFallback": "Вибачте за незручності! Надішліть звіт про помилку на нашу сторінку GitHub, де ви опишіть свою помилку.",
|
"howToFixFallback": "Вибачте за незручності! Надішліть звіт про помилку на нашу сторінку GitHub, де ви опишіть свою помилку.",
|
||||||
"github": "Переглянути на GitHub"
|
"github": "Переглянути на GitHub"
|
||||||
},
|
},
|
||||||
|
@ -386,7 +386,7 @@
|
|||||||
"themeUpload": {
|
"themeUpload": {
|
||||||
"button": "Tải lên",
|
"button": "Tải lên",
|
||||||
"uploadTheme": "Tải theme lên",
|
"uploadTheme": "Tải theme lên",
|
||||||
"description": "Tải lên AppFlowy theme của riêng bạn bằng nút bên dưới.",
|
"description": "Tải lên @:appName theme của riêng bạn bằng nút bên dưới.",
|
||||||
"loading": "Vui lòng đợi trong khi chúng tôi xác thực và tải theme của bạn lên...",
|
"loading": "Vui lòng đợi trong khi chúng tôi xác thực và tải theme của bạn lên...",
|
||||||
"uploadSuccess": "Theme của bạn đã được tải lên thành công",
|
"uploadSuccess": "Theme của bạn đã được tải lên thành công",
|
||||||
"deletionFailure": "Không xóa được theme. Hãy thử xóa nó bằng tay.",
|
"deletionFailure": "Không xóa được theme. Hãy thử xóa nó bằng tay.",
|
||||||
@ -469,11 +469,6 @@
|
|||||||
"pleaseInputYourStabilityAIKey": "vui lòng nhập khóa Stability AI của bạn",
|
"pleaseInputYourStabilityAIKey": "vui lòng nhập khóa Stability AI của bạn",
|
||||||
"clickToLogout": "Nhấn để đăng xuất"
|
"clickToLogout": "Nhấn để đăng xuất"
|
||||||
},
|
},
|
||||||
"shortcuts": {
|
|
||||||
"shortcutsLabel": "Phím tắt",
|
|
||||||
"updateShortcutStep": "Nhấn tổ hợp phím mong muốn và nhấn ENTER",
|
|
||||||
"shortcutIsAlreadyUsed": "Phím tắt này đã được sử dụng cho: {conflict}"
|
|
||||||
},
|
|
||||||
"mobile": {
|
"mobile": {
|
||||||
"personalInfo": "Thông tin cá nhân",
|
"personalInfo": "Thông tin cá nhân",
|
||||||
"username": "Tên người dùng ",
|
"username": "Tên người dùng ",
|
||||||
@ -490,6 +485,11 @@
|
|||||||
"selectLayout": "Chọn bố cục",
|
"selectLayout": "Chọn bố cục",
|
||||||
"selectStartingDay": "Chọn ngày bắt đầu",
|
"selectStartingDay": "Chọn ngày bắt đầu",
|
||||||
"version": "Phiên bản"
|
"version": "Phiên bản"
|
||||||
|
},
|
||||||
|
"shortcuts": {
|
||||||
|
"shortcutsLabel": "Phím tắt",
|
||||||
|
"updateShortcutStep": "Nhấn tổ hợp phím mong muốn và nhấn ENTER",
|
||||||
|
"shortcutIsAlreadyUsed": "Phím tắt này đã được sử dụng cho: {conflict}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid": {
|
"grid": {
|
||||||
|
@ -154,7 +154,7 @@
|
|||||||
"newBoardText": "新建看板",
|
"newBoardText": "新建看板",
|
||||||
"chat": {
|
"chat": {
|
||||||
"newChat": "AI 对话",
|
"newChat": "AI 对话",
|
||||||
"unsupportedCloudPrompt": "该功能仅在使用 AppFlowy Cloud 时可用",
|
"unsupportedCloudPrompt": "该功能仅在使用 @:appName Cloud 时可用",
|
||||||
"relatedQuestion": "相关问题",
|
"relatedQuestion": "相关问题",
|
||||||
"serverUnavailable": "服务暂时不可用,请稍后再试",
|
"serverUnavailable": "服务暂时不可用,请稍后再试",
|
||||||
"clickToRetry": "点击重试",
|
"clickToRetry": "点击重试",
|
||||||
@ -352,13 +352,17 @@
|
|||||||
"accountPage": {
|
"accountPage": {
|
||||||
"menuLabel": "我的账户",
|
"menuLabel": "我的账户",
|
||||||
"title": "我的账户",
|
"title": "我的账户",
|
||||||
"description": "自定义您的简介,管理账户安全信息和 AI API keys,或登陆您的账户",
|
|
||||||
"email": {
|
"email": {
|
||||||
"title": "邮箱",
|
"title": "邮箱",
|
||||||
"actions": {
|
"actions": {
|
||||||
"change": "更改邮箱"
|
"change": "更改邮箱"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"login": {
|
||||||
|
"title": "登录账户",
|
||||||
|
"loginLabel": "登录",
|
||||||
|
"logoutLabel": "退出登录"
|
||||||
|
},
|
||||||
"keys": {
|
"keys": {
|
||||||
"title": "AI API 密钥",
|
"title": "AI API 密钥",
|
||||||
"openAILabel": "OpenAI API 密钥",
|
"openAILabel": "OpenAI API 密钥",
|
||||||
@ -366,11 +370,7 @@
|
|||||||
"stabilityAILabel": "Stability API key",
|
"stabilityAILabel": "Stability API key",
|
||||||
"stabilityAIHint": "输入你的 Stability API Key"
|
"stabilityAIHint": "输入你的 Stability API Key"
|
||||||
},
|
},
|
||||||
"login": {
|
"description": "自定义您的简介,管理账户安全信息和 AI API keys,或登陆您的账户"
|
||||||
"title": "登录账户",
|
|
||||||
"loginLabel": "登录",
|
|
||||||
"logoutLabel": "退出登录"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"workspacePage": {
|
"workspacePage": {
|
||||||
"menuLabel": "工作区",
|
"menuLabel": "工作区",
|
||||||
@ -685,6 +685,23 @@
|
|||||||
"pleaseInputYourStabilityAIKey": "请输入您的 Stability AI 密钥",
|
"pleaseInputYourStabilityAIKey": "请输入您的 Stability AI 密钥",
|
||||||
"clickToLogout": "点击退出当前用户"
|
"clickToLogout": "点击退出当前用户"
|
||||||
},
|
},
|
||||||
|
"mobile": {
|
||||||
|
"personalInfo": "个人信息",
|
||||||
|
"username": "用户名",
|
||||||
|
"usernameEmptyError": "用户名不能为空",
|
||||||
|
"about": "关于",
|
||||||
|
"pushNotifications": "推送通知",
|
||||||
|
"support": "支持",
|
||||||
|
"joinDiscord": "在 Discord 中加入我们",
|
||||||
|
"privacyPolicy": "隐私政策",
|
||||||
|
"userAgreement": "用户协议",
|
||||||
|
"termsAndConditions": "条款和条件",
|
||||||
|
"userprofileError": "无法加载用户配置文件",
|
||||||
|
"userprofileErrorDescription": "请尝试注销并重新登录以检查问题是否仍然存在。",
|
||||||
|
"selectLayout": "选择布局",
|
||||||
|
"selectStartingDay": "选择开始日期",
|
||||||
|
"version": "版本"
|
||||||
|
},
|
||||||
"shortcuts": {
|
"shortcuts": {
|
||||||
"shortcutsLabel": "快捷方式",
|
"shortcutsLabel": "快捷方式",
|
||||||
"command": "指令",
|
"command": "指令",
|
||||||
@ -705,23 +722,6 @@
|
|||||||
"textAlignRight": "右对齐文本",
|
"textAlignRight": "右对齐文本",
|
||||||
"codeBlockDeleteTwoSpaces": "删除代码块中行首的两个空格"
|
"codeBlockDeleteTwoSpaces": "删除代码块中行首的两个空格"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"mobile": {
|
|
||||||
"personalInfo": "个人信息",
|
|
||||||
"username": "用户名",
|
|
||||||
"usernameEmptyError": "用户名不能为空",
|
|
||||||
"about": "关于",
|
|
||||||
"pushNotifications": "推送通知",
|
|
||||||
"support": "支持",
|
|
||||||
"joinDiscord": "在 Discord 中加入我们",
|
|
||||||
"privacyPolicy": "隐私政策",
|
|
||||||
"userAgreement": "用户协议",
|
|
||||||
"termsAndConditions": "条款和条件",
|
|
||||||
"userprofileError": "无法加载用户配置文件",
|
|
||||||
"userprofileErrorDescription": "请尝试注销并重新登录以检查问题是否仍然存在。",
|
|
||||||
"selectLayout": "选择布局",
|
|
||||||
"selectStartingDay": "选择开始日期",
|
|
||||||
"version": "版本"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid": {
|
"grid": {
|
||||||
|
@ -318,7 +318,6 @@
|
|||||||
"accountPage": {
|
"accountPage": {
|
||||||
"menuLabel": "我的帳號",
|
"menuLabel": "我的帳號",
|
||||||
"title": "我的帳號",
|
"title": "我的帳號",
|
||||||
"description": "自訂您的個人資料、管理帳戶安全性和 AI API 金鑰,或登入您的帳號",
|
|
||||||
"general": {
|
"general": {
|
||||||
"title": "帳號名稱和個人資料圖片",
|
"title": "帳號名稱和個人資料圖片",
|
||||||
"changeProfilePicture": "更改個人資料圖片"
|
"changeProfilePicture": "更改個人資料圖片"
|
||||||
@ -329,6 +328,11 @@
|
|||||||
"change": "更改電子郵件"
|
"change": "更改電子郵件"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"login": {
|
||||||
|
"title": "帳號登入",
|
||||||
|
"loginLabel": "登入",
|
||||||
|
"logoutLabel": "登出"
|
||||||
|
},
|
||||||
"keys": {
|
"keys": {
|
||||||
"title": "AI API 金鑰",
|
"title": "AI API 金鑰",
|
||||||
"openAILabel": "Open AI API 金鑰",
|
"openAILabel": "Open AI API 金鑰",
|
||||||
@ -338,11 +342,7 @@
|
|||||||
"stabilityAITooltip": "以Stability API 金鑰使用AI 模型",
|
"stabilityAITooltip": "以Stability API 金鑰使用AI 模型",
|
||||||
"stabilityAIHint": "輸入您的Stability API 金鑰"
|
"stabilityAIHint": "輸入您的Stability API 金鑰"
|
||||||
},
|
},
|
||||||
"login": {
|
"description": "自訂您的個人資料、管理帳戶安全性和 AI API 金鑰,或登入您的帳號"
|
||||||
"title": "帳號登入",
|
|
||||||
"loginLabel": "登入",
|
|
||||||
"logoutLabel": "登出"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"menu": {
|
"menu": {
|
||||||
"appearance": "外觀",
|
"appearance": "外觀",
|
||||||
@ -546,20 +546,6 @@
|
|||||||
"pleaseInputYourStabilityAIKey": "請輸入您的 Stability AI 金鑰",
|
"pleaseInputYourStabilityAIKey": "請輸入您的 Stability AI 金鑰",
|
||||||
"clickToLogout": "點選以登出目前使用者"
|
"clickToLogout": "點選以登出目前使用者"
|
||||||
},
|
},
|
||||||
"shortcuts": {
|
|
||||||
"shortcutsLabel": "快捷鍵",
|
|
||||||
"command": "指令",
|
|
||||||
"keyBinding": "鍵盤綁定",
|
|
||||||
"addNewCommand": "新增指令",
|
|
||||||
"updateShortcutStep": "按下您想要的鍵盤組合並按下 ENTER",
|
|
||||||
"shortcutIsAlreadyUsed": "此快捷鍵已被使用於:{conflict}",
|
|
||||||
"resetToDefault": "重設為預設鍵盤綁定",
|
|
||||||
"couldNotLoadErrorMsg": "無法載入快捷鍵,請再試一次",
|
|
||||||
"couldNotSaveErrorMsg": "無法儲存快捷鍵,請再試一次",
|
|
||||||
"commands": {
|
|
||||||
"textAlignRight": "向右對齊文字"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"mobile": {
|
"mobile": {
|
||||||
"personalInfo": "個人資料",
|
"personalInfo": "個人資料",
|
||||||
"username": "使用者名稱",
|
"username": "使用者名稱",
|
||||||
@ -576,6 +562,20 @@
|
|||||||
"selectLayout": "選擇版面配置",
|
"selectLayout": "選擇版面配置",
|
||||||
"selectStartingDay": "選擇一週的起始日",
|
"selectStartingDay": "選擇一週的起始日",
|
||||||
"version": "版本"
|
"version": "版本"
|
||||||
|
},
|
||||||
|
"shortcuts": {
|
||||||
|
"shortcutsLabel": "快捷鍵",
|
||||||
|
"command": "指令",
|
||||||
|
"keyBinding": "鍵盤綁定",
|
||||||
|
"addNewCommand": "新增指令",
|
||||||
|
"updateShortcutStep": "按下您想要的鍵盤組合並按下 ENTER",
|
||||||
|
"shortcutIsAlreadyUsed": "此快捷鍵已被使用於:{conflict}",
|
||||||
|
"resetToDefault": "重設為預設鍵盤綁定",
|
||||||
|
"couldNotLoadErrorMsg": "無法載入快捷鍵,請再試一次",
|
||||||
|
"couldNotSaveErrorMsg": "無法儲存快捷鍵,請再試一次",
|
||||||
|
"commands": {
|
||||||
|
"textAlignRight": "向右對齊文字"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"grid": {
|
"grid": {
|
||||||
|
@ -11,6 +11,7 @@ use flowy_document::entities::DocumentDataPB;
|
|||||||
use flowy_document::manager::DocumentManager;
|
use flowy_document::manager::DocumentManager;
|
||||||
use flowy_document::parser::json::parser::JsonToDocumentParser;
|
use flowy_document::parser::json::parser::JsonToDocumentParser;
|
||||||
use flowy_error::FlowyError;
|
use flowy_error::FlowyError;
|
||||||
|
use flowy_folder::entities::{CreateViewParams, ViewLayoutPB};
|
||||||
use flowy_folder::manager::{FolderManager, FolderUser};
|
use flowy_folder::manager::{FolderManager, FolderUser};
|
||||||
use flowy_folder::share::ImportType;
|
use flowy_folder::share::ImportType;
|
||||||
use flowy_folder::view_operation::{
|
use flowy_folder::view_operation::{
|
||||||
@ -183,17 +184,13 @@ impl FolderOperationHandler for DocumentFolderOperation {
|
|||||||
fn create_view_with_view_data(
|
fn create_view_with_view_data(
|
||||||
&self,
|
&self,
|
||||||
user_id: i64,
|
user_id: i64,
|
||||||
view_id: &str,
|
params: CreateViewParams,
|
||||||
_name: &str,
|
|
||||||
data: Vec<u8>,
|
|
||||||
layout: ViewLayout,
|
|
||||||
_meta: HashMap<String, String>,
|
|
||||||
) -> FutureResult<(), FlowyError> {
|
) -> FutureResult<(), FlowyError> {
|
||||||
debug_assert_eq!(layout, ViewLayout::Document);
|
debug_assert_eq!(params.layout, ViewLayoutPB::Document);
|
||||||
let view_id = view_id.to_string();
|
let view_id = params.view_id.to_string();
|
||||||
let manager = self.0.clone();
|
let manager = self.0.clone();
|
||||||
FutureResult::new(async move {
|
FutureResult::new(async move {
|
||||||
let data = DocumentDataPB::try_from(Bytes::from(data))?;
|
let data = DocumentDataPB::try_from(Bytes::from(params.initial_data))?;
|
||||||
manager
|
manager
|
||||||
.create_document(user_id, &view_id, Some(data.into()))
|
.create_document(user_id, &view_id, Some(data.into()))
|
||||||
.await?;
|
.await?;
|
||||||
@ -327,40 +324,43 @@ impl FolderOperationHandler for DatabaseFolderOperation {
|
|||||||
fn create_view_with_view_data(
|
fn create_view_with_view_data(
|
||||||
&self,
|
&self,
|
||||||
_user_id: i64,
|
_user_id: i64,
|
||||||
view_id: &str,
|
params: CreateViewParams,
|
||||||
name: &str,
|
|
||||||
data: Vec<u8>,
|
|
||||||
layout: ViewLayout,
|
|
||||||
meta: HashMap<String, String>,
|
|
||||||
) -> FutureResult<(), FlowyError> {
|
) -> FutureResult<(), FlowyError> {
|
||||||
match CreateDatabaseExtParams::from_map(meta) {
|
match CreateDatabaseExtParams::from_map(params.meta.clone()) {
|
||||||
None => {
|
None => {
|
||||||
let database_manager = self.0.clone();
|
let database_manager = self.0.clone();
|
||||||
let view_id = view_id.to_string();
|
let view_id = params.view_id.to_string();
|
||||||
FutureResult::new(async move {
|
FutureResult::new(async move {
|
||||||
database_manager
|
database_manager
|
||||||
.create_database_with_database_data(&view_id, data)
|
.create_database_with_database_data(&view_id, params.initial_data)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
Some(params) => {
|
Some(database_params) => {
|
||||||
let database_manager = self.0.clone();
|
let database_manager = self.0.clone();
|
||||||
|
|
||||||
let layout = match layout {
|
let layout = match params.layout {
|
||||||
ViewLayout::Board => DatabaseLayoutPB::Board,
|
ViewLayoutPB::Board => DatabaseLayoutPB::Board,
|
||||||
ViewLayout::Calendar => DatabaseLayoutPB::Calendar,
|
ViewLayoutPB::Calendar => DatabaseLayoutPB::Calendar,
|
||||||
ViewLayout::Grid => DatabaseLayoutPB::Grid,
|
ViewLayoutPB::Grid => DatabaseLayoutPB::Grid,
|
||||||
ViewLayout::Document | ViewLayout::Chat => {
|
ViewLayoutPB::Document | ViewLayoutPB::Chat => {
|
||||||
return FutureResult::new(async move { Err(FlowyError::not_support()) });
|
return FutureResult::new(async move { Err(FlowyError::not_support()) });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let name = name.to_string();
|
let name = params.name.to_string();
|
||||||
let database_view_id = view_id.to_string();
|
let database_view_id = params.view_id.to_string();
|
||||||
|
let database_parent_view_id = params.parent_view_id.to_string();
|
||||||
|
|
||||||
FutureResult::new(async move {
|
FutureResult::new(async move {
|
||||||
database_manager
|
database_manager
|
||||||
.create_linked_view(name, layout.into(), params.database_id, database_view_id)
|
.create_linked_view(
|
||||||
|
name,
|
||||||
|
layout.into(),
|
||||||
|
database_params.database_id,
|
||||||
|
database_view_id,
|
||||||
|
database_parent_view_id,
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
@ -529,11 +529,7 @@ impl FolderOperationHandler for ChatFolderOperation {
|
|||||||
fn create_view_with_view_data(
|
fn create_view_with_view_data(
|
||||||
&self,
|
&self,
|
||||||
_user_id: i64,
|
_user_id: i64,
|
||||||
_view_id: &str,
|
_params: CreateViewParams,
|
||||||
_name: &str,
|
|
||||||
_data: Vec<u8>,
|
|
||||||
_layout: ViewLayout,
|
|
||||||
_meta: HashMap<String, String>,
|
|
||||||
) -> FutureResult<(), FlowyError> {
|
) -> FutureResult<(), FlowyError> {
|
||||||
FutureResult::new(async move { Err(FlowyError::not_support()) })
|
FutureResult::new(async move { Err(FlowyError::not_support()) })
|
||||||
}
|
}
|
||||||
|
@ -323,18 +323,23 @@ impl DatabaseManager {
|
|||||||
layout: DatabaseLayout,
|
layout: DatabaseLayout,
|
||||||
database_id: String,
|
database_id: String,
|
||||||
database_view_id: String,
|
database_view_id: String,
|
||||||
|
database_parent_view_id: String,
|
||||||
) -> FlowyResult<()> {
|
) -> FlowyResult<()> {
|
||||||
let wdb = self.get_database_indexer().await?;
|
let wdb = self.get_database_indexer().await?;
|
||||||
let mut params = CreateViewParams::new(database_id.clone(), database_view_id, name, layout);
|
let mut params = CreateViewParams::new(database_id.clone(), database_view_id, name, layout);
|
||||||
if let Some(database) = wdb.get_database(&database_id).await {
|
if let Some(database) = wdb.get_database(&database_id).await {
|
||||||
let (field, layout_setting) = DatabaseLayoutDepsResolver::new(database, layout)
|
let (field, layout_setting, field_settings_map) =
|
||||||
.resolve_deps_when_create_database_linked_view();
|
DatabaseLayoutDepsResolver::new(database, layout)
|
||||||
|
.resolve_deps_when_create_database_linked_view(&database_parent_view_id);
|
||||||
if let Some(field) = field {
|
if let Some(field) = field {
|
||||||
params = params.with_deps_fields(vec![field], vec![default_field_settings_by_layout_map()]);
|
params = params.with_deps_fields(vec![field], vec![default_field_settings_by_layout_map()]);
|
||||||
}
|
}
|
||||||
if let Some(layout_setting) = layout_setting {
|
if let Some(layout_setting) = layout_setting {
|
||||||
params = params.with_layout_setting(layout_setting);
|
params = params.with_layout_setting(layout_setting);
|
||||||
}
|
}
|
||||||
|
if let Some(field_settings_map) = field_settings_map {
|
||||||
|
params = params.with_field_settings_map(field_settings_map);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
wdb.create_database_linked_view(params).await?;
|
wdb.create_database_linked_view(params).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
use collab_database::database::{gen_field_id, MutexDatabase};
|
use collab_database::database::{gen_field_id, MutexDatabase};
|
||||||
use collab_database::fields::Field;
|
use collab_database::fields::Field;
|
||||||
use collab_database::views::{DatabaseLayout, LayoutSetting, OrderObjectPosition};
|
use collab_database::views::{
|
||||||
|
DatabaseLayout, FieldSettingsByFieldIdMap, LayoutSetting, OrderObjectPosition,
|
||||||
|
};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::entities::FieldType;
|
use crate::entities::FieldType;
|
||||||
@ -28,23 +30,40 @@ impl DatabaseLayoutDepsResolver {
|
|||||||
|
|
||||||
pub fn resolve_deps_when_create_database_linked_view(
|
pub fn resolve_deps_when_create_database_linked_view(
|
||||||
&self,
|
&self,
|
||||||
) -> (Option<Field>, Option<LayoutSetting>) {
|
view_id: &str,
|
||||||
|
) -> (
|
||||||
|
Option<Field>,
|
||||||
|
Option<LayoutSetting>,
|
||||||
|
Option<FieldSettingsByFieldIdMap>,
|
||||||
|
) {
|
||||||
match self.database_layout {
|
match self.database_layout {
|
||||||
DatabaseLayout::Grid => (None, None),
|
DatabaseLayout::Grid => (None, None, None),
|
||||||
DatabaseLayout::Board => {
|
DatabaseLayout::Board => {
|
||||||
let layout_settings = BoardLayoutSetting::new().into();
|
let layout_settings = BoardLayoutSetting::new().into();
|
||||||
if !self
|
|
||||||
|
let field = if !self
|
||||||
.database
|
.database
|
||||||
.lock()
|
.lock()
|
||||||
.get_fields(None)
|
.get_fields(None)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.any(|field| FieldType::from(field.field_type).can_be_group())
|
.any(|field| FieldType::from(field.field_type).can_be_group())
|
||||||
{
|
{
|
||||||
let select_field = self.create_select_field();
|
Some(self.create_select_field())
|
||||||
(Some(select_field), Some(layout_settings))
|
|
||||||
} else {
|
} else {
|
||||||
(None, Some(layout_settings))
|
None
|
||||||
}
|
};
|
||||||
|
|
||||||
|
let field_settings_map = self.database.lock().get_field_settings(view_id, None);
|
||||||
|
tracing::info!(
|
||||||
|
"resolve_deps_when_create_database_linked_view {:?}",
|
||||||
|
field_settings_map
|
||||||
|
);
|
||||||
|
|
||||||
|
(
|
||||||
|
field,
|
||||||
|
Some(layout_settings),
|
||||||
|
Some(field_settings_map.into()),
|
||||||
|
)
|
||||||
},
|
},
|
||||||
DatabaseLayout::Calendar => {
|
DatabaseLayout::Calendar => {
|
||||||
match self
|
match self
|
||||||
@ -56,12 +75,12 @@ impl DatabaseLayoutDepsResolver {
|
|||||||
{
|
{
|
||||||
Some(field) => {
|
Some(field) => {
|
||||||
let layout_setting = CalendarLayoutSetting::new(field.id).into();
|
let layout_setting = CalendarLayoutSetting::new(field.id).into();
|
||||||
(None, Some(layout_setting))
|
(None, Some(layout_setting), None)
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
let date_field = self.create_date_field();
|
let date_field = self.create_date_field();
|
||||||
let layout_setting = CalendarLayoutSetting::new(date_field.clone().id).into();
|
let layout_setting = CalendarLayoutSetting::new(date_field.clone().id).into();
|
||||||
(Some(date_field), Some(layout_setting))
|
(Some(date_field), Some(layout_setting), None)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -584,6 +584,16 @@ pub struct DuplicateViewPayloadPB {
|
|||||||
|
|
||||||
#[pb(index = 3)]
|
#[pb(index = 3)]
|
||||||
pub include_children: bool,
|
pub include_children: bool,
|
||||||
|
|
||||||
|
// duplicate the view to the specified parent view.
|
||||||
|
// if the parent_view_id is None, the view will be duplicated to the same parent view.
|
||||||
|
#[pb(index = 4, one_of)]
|
||||||
|
pub parent_view_id: Option<String>,
|
||||||
|
|
||||||
|
// The suffix of the duplicated view name.
|
||||||
|
// If the suffix is None, the duplicated view will have the same name with (copy) suffix.
|
||||||
|
#[pb(index = 5, one_of)]
|
||||||
|
pub suffix: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -593,6 +603,10 @@ pub struct DuplicateViewParams {
|
|||||||
pub open_after_duplicate: bool,
|
pub open_after_duplicate: bool,
|
||||||
|
|
||||||
pub include_children: bool,
|
pub include_children: bool,
|
||||||
|
|
||||||
|
pub parent_view_id: Option<String>,
|
||||||
|
|
||||||
|
pub suffix: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryInto<DuplicateViewParams> for DuplicateViewPayloadPB {
|
impl TryInto<DuplicateViewParams> for DuplicateViewPayloadPB {
|
||||||
@ -604,6 +618,8 @@ impl TryInto<DuplicateViewParams> for DuplicateViewPayloadPB {
|
|||||||
view_id,
|
view_id,
|
||||||
open_after_duplicate: self.open_after_duplicate,
|
open_after_duplicate: self.open_after_duplicate,
|
||||||
include_children: self.include_children,
|
include_children: self.include_children,
|
||||||
|
parent_view_id: self.parent_view_id,
|
||||||
|
suffix: self.suffix,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -381,9 +381,8 @@ impl FolderManager {
|
|||||||
let view_layout: ViewLayout = params.layout.clone().into();
|
let view_layout: ViewLayout = params.layout.clone().into();
|
||||||
let handler = self.get_handler(&view_layout)?;
|
let handler = self.get_handler(&view_layout)?;
|
||||||
let user_id = self.user.user_id()?;
|
let user_id = self.user.user_id()?;
|
||||||
let meta = params.meta.clone();
|
|
||||||
|
|
||||||
if meta.is_empty() && params.initial_data.is_empty() {
|
if params.meta.is_empty() && params.initial_data.is_empty() {
|
||||||
tracing::trace!("Create view with build-in data");
|
tracing::trace!("Create view with build-in data");
|
||||||
handler
|
handler
|
||||||
.create_built_in_view(user_id, ¶ms.view_id, ¶ms.name, view_layout.clone())
|
.create_built_in_view(user_id, ¶ms.view_id, ¶ms.name, view_layout.clone())
|
||||||
@ -391,14 +390,7 @@ impl FolderManager {
|
|||||||
} else {
|
} else {
|
||||||
tracing::trace!("Create view with view data");
|
tracing::trace!("Create view with view data");
|
||||||
handler
|
handler
|
||||||
.create_view_with_view_data(
|
.create_view_with_view_data(user_id, params.clone())
|
||||||
user_id,
|
|
||||||
¶ms.view_id,
|
|
||||||
¶ms.name,
|
|
||||||
params.initial_data.clone(),
|
|
||||||
view_layout.clone(),
|
|
||||||
meta,
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -754,12 +746,17 @@ impl FolderManager {
|
|||||||
let view = self
|
let view = self
|
||||||
.with_folder(|| None, |folder| folder.views.get_view(¶ms.view_id))
|
.with_folder(|| None, |folder| folder.views.get_view(¶ms.view_id))
|
||||||
.ok_or_else(|| FlowyError::record_not_found().with_context("Can't duplicate the view"))?;
|
.ok_or_else(|| FlowyError::record_not_found().with_context("Can't duplicate the view"))?;
|
||||||
|
let parent_view_id = params
|
||||||
|
.parent_view_id
|
||||||
|
.clone()
|
||||||
|
.unwrap_or(view.parent_view_id.clone());
|
||||||
self
|
self
|
||||||
.duplicate_view_with_parent_id(
|
.duplicate_view_with_parent_id(
|
||||||
&view.id,
|
&view.id,
|
||||||
&view.parent_view_id,
|
&parent_view_id,
|
||||||
params.open_after_duplicate,
|
params.open_after_duplicate,
|
||||||
params.include_children,
|
params.include_children,
|
||||||
|
params.suffix,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -774,6 +771,7 @@ impl FolderManager {
|
|||||||
parent_view_id: &str,
|
parent_view_id: &str,
|
||||||
open_after_duplicated: bool,
|
open_after_duplicated: bool,
|
||||||
include_children: bool,
|
include_children: bool,
|
||||||
|
suffix: Option<String>,
|
||||||
) -> Result<(), FlowyError> {
|
) -> Result<(), FlowyError> {
|
||||||
if view_id == parent_view_id {
|
if view_id == parent_view_id {
|
||||||
return Err(FlowyError::new(
|
return Err(FlowyError::new(
|
||||||
@ -790,6 +788,7 @@ impl FolderManager {
|
|||||||
let mut is_source_view = true;
|
let mut is_source_view = true;
|
||||||
// use a stack to duplicate the view and its children
|
// use a stack to duplicate the view and its children
|
||||||
let mut stack = vec![(view_id.to_string(), parent_view_id.to_string())];
|
let mut stack = vec![(view_id.to_string(), parent_view_id.to_string())];
|
||||||
|
let suffix = suffix.unwrap_or(" (copy)".to_string());
|
||||||
|
|
||||||
while let Some((current_view_id, current_parent_id)) = stack.pop() {
|
while let Some((current_view_id, current_parent_id)) = stack.pop() {
|
||||||
let view = self
|
let view = self
|
||||||
@ -825,7 +824,7 @@ impl FolderManager {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let name = if is_source_view {
|
let name = if is_source_view {
|
||||||
format!("{} (copy)", &view.name)
|
format!("{}{}", &view.name, suffix)
|
||||||
} else {
|
} else {
|
||||||
view.name.clone()
|
view.name.clone()
|
||||||
};
|
};
|
||||||
|
@ -70,11 +70,7 @@ pub trait FolderOperationHandler {
|
|||||||
fn create_view_with_view_data(
|
fn create_view_with_view_data(
|
||||||
&self,
|
&self,
|
||||||
user_id: i64,
|
user_id: i64,
|
||||||
view_id: &str,
|
params: CreateViewParams,
|
||||||
name: &str,
|
|
||||||
data: Vec<u8>,
|
|
||||||
layout: ViewLayout,
|
|
||||||
meta: HashMap<String, String>,
|
|
||||||
) -> FutureResult<(), FlowyError>;
|
) -> FutureResult<(), FlowyError>;
|
||||||
|
|
||||||
/// Create a view with the pre-defined data.
|
/// Create a view with the pre-defined data.
|
||||||
|
Loading…
Reference in New Issue
Block a user