mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: merge remote-tracking branch 'main' into develop (#2530)
* feat: show unscheduled events in calendar toolbar (#2411)
* refactor: use same show row detail function
* fix: adjust popover offset
* feat: show unscheduled events in toolbar
* chore: apply suggestions from Xazin
* refactor: refactor list item into separate widget
---------
Co-authored-by: Nathan.fooo <86001920+appflowy@users.noreply.github.com>
* fix: default include time (#2444)
* fix: default include time
* chore: clarify logic and add comments
* chore: bump version 0.1.4 (#2455)
* chore: Update README.md
Update product screenshots
* fix: wrong day of week (#2468)
* feat: select which properties to show in calendar (#2482)
* feat: improve sidebar item dragged appearance (#2471)
* fix: show delete icon for document icon properly (#2475)
* feat: add hover effect on an event card (#2487)
* chore: delete unncessary openCard method in RowCardContainer
* chore: delete unnessary code and add comment
* chore: update editor v0.1.12 and format the readme (#2489)
* fix: number sort (#2507)
* bump version 0.1.5 (#2506)
* chore: bump version 0.1.5
* fix: could not trigger slash menu after inserting an emoji
* Revert "feat: add hover effect on an event card (#2487)"
This reverts commit f0a4b4b77d
.
* feat: add hover effect on an event card
* fix: #2469 duplicated cover
* chore: update changelog.md (#2510)
* chore: Update README.md
Add a screenshot of the calendar view
* fix: some regressions
---------
Co-authored-by: Nathan.fooo <86001920+appflowy@users.noreply.github.com>
Co-authored-by: Lucas.Xu <lucas.xu@appflowy.io>
Co-authored-by: Annie <anqi.annie.wang@gmail.com>
Co-authored-by: Yijing Huang <hyj891204@gmail.com>
This commit is contained in:
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -138,7 +138,7 @@ jobs:
|
|||||||
job:
|
job:
|
||||||
- {
|
- {
|
||||||
target: x86_64-apple-darwin,
|
target: x86_64-apple-darwin,
|
||||||
os: macos-10.15,
|
os: macos-11,
|
||||||
extra-build-args: "",
|
extra-build-args: "",
|
||||||
}
|
}
|
||||||
steps:
|
steps:
|
||||||
|
22
CHANGELOG.md
22
CHANGELOG.md
@ -1,5 +1,27 @@
|
|||||||
# Release Notes
|
# Release Notes
|
||||||
|
|
||||||
|
## Version 0.1.5 - 11/05/2023
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
- Fix: calendar dates don't match with weekdays.
|
||||||
|
- Fix: sort numbers in Grid.
|
||||||
|
|
||||||
|
## Version 0.1.4 - 04/05/2023
|
||||||
|
|
||||||
|
### New features
|
||||||
|
- Use AppFlowy’s calendar views to plan and manage tasks and deadlines.
|
||||||
|
- Writing can be improved with the help of OpenAI.
|
||||||
|
|
||||||
|
## Version 0.1.3 - 24/04/2023
|
||||||
|
|
||||||
|
### New features
|
||||||
|
- Launch the official Dark Mode.
|
||||||
|
- Customize the font color and highlight color by setting a hex color value and an opacity level.
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
- Fix: the slash menu can be triggered by all other keyboards than English.
|
||||||
|
- Fix: convert the single asterisk to italic text and the double asterisks to bold text.
|
||||||
|
|
||||||
## Version 0.1.2 - 03/28/2023
|
## Version 0.1.2 - 03/28/2023
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
@ -23,9 +23,11 @@ You are in charge of your data and customizations.
|
|||||||
<a href="https://twitter.com/appflowy"><b>Twitter</b></a>
|
<a href="https://twitter.com/appflowy"><b>Twitter</b></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center"><img src="https://user-images.githubusercontent.com/12026239/200787830-96be260b-d0a0-4152-864e-6730b19095cd.png" alt="The Open Source Alternative To Notion." width="1000px" /></p>
|
<p align="center"><img src="https://user-images.githubusercontent.com/12026239/236664610-fc209a97-815e-4716-af07-d94a859d1907.png" alt="AppFlowy Docs & Notes & Wikis" width="1000px" /></p>
|
||||||
<p align="center"><img src="https://user-images.githubusercontent.com/12026239/174753177-98e4c899-2356-4137-bb42-374bba2b127b.png" alt="The Open Source Alternative To Notion." width="1000px" /></p>
|
<p align="center"><img src="https://user-images.githubusercontent.com/12026239/236664628-5def2450-914a-4b2d-b907-92b7476b9863.png" alt="AppFlowy Databases for Tasks and Projects" width="1000px" /></p>
|
||||||
<p align="center"><img src="https://user-images.githubusercontent.com/12026239/190650183-a940f1e0-a2c5-4797-ab3a-56758f6f696c.png" alt="The Open Source Alternative To Notion." width="1000px" /></p>
|
<p align="center"><img src="https://user-images.githubusercontent.com/12026239/236664642-22e26c1b-5eae-4635-9aa6-b12ecf1c3c46.png" alt="AppFlowy Kanban Board for To-Dos" width="1000px" /></p>
|
||||||
|
<p align="center"><img src="https://github.com/AppFlowy-IO/AppFlowy/assets/12026239/6be93d2b-a5c5-48a9-b7cf-c599d5f5140c" alt="AppFlowy Calendars for Plan and Manage Content" width="1000px" /></p>
|
||||||
|
<p align="center"><img src="https://user-images.githubusercontent.com/12026239/236664657-dc5291f3-67b0-4a43-a818-640e92735deb.png" alt="AppFlowy OpenAI GPT Writers" width="1000px" /></p>
|
||||||
|
|
||||||
## User Installation
|
## User Installation
|
||||||
|
|
||||||
|
@ -23,7 +23,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"
|
||||||
CURRENT_APP_VERSION = "0.1.3"
|
CURRENT_APP_VERSION = "0.1.5"
|
||||||
FLUTTER_DESKTOP_FEATURES = "dart,rev-sqlite"
|
FLUTTER_DESKTOP_FEATURES = "dart,rev-sqlite"
|
||||||
PRODUCT_NAME = "AppFlowy"
|
PRODUCT_NAME = "AppFlowy"
|
||||||
# CRATE_TYPE: https://doc.rust-lang.org/reference/linkage.html
|
# CRATE_TYPE: https://doc.rust-lang.org/reference/linkage.html
|
||||||
|
@ -418,7 +418,9 @@
|
|||||||
"showWeekNumbers": "Show week numbers",
|
"showWeekNumbers": "Show week numbers",
|
||||||
"showWeekends": "Show weekends",
|
"showWeekends": "Show weekends",
|
||||||
"firstDayOfWeek": "Start week on",
|
"firstDayOfWeek": "Start week on",
|
||||||
"layoutDateField": "Layout calendar by"
|
"layoutDateField": "Layout calendar by",
|
||||||
|
"noDateTitle": "No Date",
|
||||||
|
"emptyNoDate": "No unscheduled events"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -51,5 +51,6 @@ class CalendarSettingEvent with _$CalendarSettingEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum CalendarSettingAction {
|
enum CalendarSettingAction {
|
||||||
|
properties,
|
||||||
layout,
|
layout,
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,23 @@
|
|||||||
import 'package:appflowy/plugins/database_view/application/row/row_cache.dart';
|
import 'package:appflowy/plugins/database_view/application/row/row_cache.dart';
|
||||||
import 'package:appflowy/plugins/database_view/application/row/row_data_controller.dart';
|
|
||||||
import 'package:appflowy/plugins/database_view/widgets/card/card.dart';
|
import 'package:appflowy/plugins/database_view/widgets/card/card.dart';
|
||||||
import 'package:appflowy/plugins/database_view/widgets/card/card_cell_builder.dart';
|
import 'package:appflowy/plugins/database_view/widgets/card/card_cell_builder.dart';
|
||||||
import 'package:appflowy/plugins/database_view/widgets/card/cells/card_cell.dart';
|
import 'package:appflowy/plugins/database_view/widgets/card/cells/card_cell.dart';
|
||||||
import 'package:appflowy/plugins/database_view/widgets/card/cells/number_card_cell.dart';
|
import 'package:appflowy/plugins/database_view/widgets/card/cells/number_card_cell.dart';
|
||||||
import 'package:appflowy/plugins/database_view/widgets/card/cells/url_card_cell.dart';
|
import 'package:appflowy/plugins/database_view/widgets/card/cells/url_card_cell.dart';
|
||||||
import 'package:appflowy/plugins/database_view/widgets/row/cell_builder.dart';
|
|
||||||
import 'package:appflowy/plugins/database_view/widgets/row/row_detail.dart';
|
|
||||||
import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.dart';
|
import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra/image.dart';
|
import 'package:flowy_infra/image.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:flowy_infra_ui/style_widget/hover.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import '../../grid/presentation/layout/sizes.dart';
|
import '../../grid/presentation/layout/sizes.dart';
|
||||||
import '../../widgets/row/cells/select_option_cell/extension.dart';
|
import '../../widgets/row/cells/select_option_cell/extension.dart';
|
||||||
import '../application/calendar_bloc.dart';
|
import '../application/calendar_bloc.dart';
|
||||||
|
import 'calendar_page.dart';
|
||||||
|
|
||||||
class CalendarDayCard extends StatelessWidget {
|
class CalendarDayCard extends StatelessWidget {
|
||||||
final String viewId;
|
final String viewId;
|
||||||
@ -102,7 +101,7 @@ class CalendarDayCard extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GestureDetector _buildCard(BuildContext context, CalendarDayEvent event) {
|
Widget _buildCard(BuildContext context, CalendarDayEvent event) {
|
||||||
final styles = <FieldType, CardCellStyle>{
|
final styles = <FieldType, CardCellStyle>{
|
||||||
FieldType.Number: NumberCardCellStyle(10),
|
FieldType.Number: NumberCardCellStyle(10),
|
||||||
FieldType.URL: URLCardCellStyle(10),
|
FieldType.URL: URLCardCellStyle(10),
|
||||||
@ -193,7 +192,12 @@ class CalendarDayCard extends StatelessWidget {
|
|||||||
cardData: event.dateFieldId,
|
cardData: event.dateFieldId,
|
||||||
isEditing: false,
|
isEditing: false,
|
||||||
cellBuilder: cellBuilder,
|
cellBuilder: cellBuilder,
|
||||||
openCard: (context) => _showRowDetailPage(event, context),
|
openCard: (context) => showEventDetails(
|
||||||
|
context: context,
|
||||||
|
event: event,
|
||||||
|
viewId: viewId,
|
||||||
|
rowCache: _rowCache,
|
||||||
|
),
|
||||||
styleConfiguration: const RowCardStyleConfiguration(
|
styleConfiguration: const RowCardStyleConfiguration(
|
||||||
showAccessory: false,
|
showAccessory: false,
|
||||||
cellPadding: EdgeInsets.zero,
|
cellPadding: EdgeInsets.zero,
|
||||||
@ -203,10 +207,11 @@ class CalendarDayCard extends StatelessWidget {
|
|||||||
onEndEditing: () {},
|
onEndEditing: () {},
|
||||||
);
|
);
|
||||||
|
|
||||||
return GestureDetector(
|
return FlowyHover(
|
||||||
onTap: () => _showRowDetailPage(event, context),
|
style: HoverStyle(
|
||||||
child: MouseRegion(
|
hoverColor: Theme.of(context).colorScheme.tertiaryContainer,
|
||||||
cursor: SystemMouseCursors.click,
|
foregroundColorOnHover: Theme.of(context).colorScheme.onBackground,
|
||||||
|
),
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 2),
|
padding: const EdgeInsets.symmetric(horizontal: 2),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
@ -220,27 +225,6 @@ class CalendarDayCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: card,
|
child: card,
|
||||||
),
|
),
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _showRowDetailPage(CalendarDayEvent event, BuildContext context) {
|
|
||||||
final dataController = RowController(
|
|
||||||
rowId: event.eventId,
|
|
||||||
viewId: viewId,
|
|
||||||
rowCache: _rowCache,
|
|
||||||
);
|
|
||||||
|
|
||||||
FlowyOverlay.show(
|
|
||||||
context: context,
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return RowDetailPage(
|
|
||||||
cellBuilder: GridCellBuilder(
|
|
||||||
cellCache: _rowCache.cellCache,
|
|
||||||
),
|
|
||||||
dataController: dataController,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
import '../../application/row/row_cache.dart';
|
||||||
import '../../application/row/row_data_controller.dart';
|
import '../../application/row/row_data_controller.dart';
|
||||||
import '../../widgets/row/cell_builder.dart';
|
import '../../widgets/row/cell_builder.dart';
|
||||||
import '../../widgets/row/row_detail.dart';
|
import '../../widgets/row/row_detail.dart';
|
||||||
@ -76,7 +77,12 @@ class _CalendarPageState extends State<CalendarPage> {
|
|||||||
listenWhen: (p, c) => p.editEvent != c.editEvent,
|
listenWhen: (p, c) => p.editEvent != c.editEvent,
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
if (state.editEvent != null) {
|
if (state.editEvent != null) {
|
||||||
_showEditEventPage(state.editEvent!.event!, context);
|
showEventDetails(
|
||||||
|
context: context,
|
||||||
|
event: state.editEvent!.event!,
|
||||||
|
viewId: widget.view.id,
|
||||||
|
rowCache: _calendarBloc.rowCache,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -165,8 +171,9 @@ class _CalendarPageState extends State<CalendarPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _headerWeekDayBuilder(day) {
|
Widget _headerWeekDayBuilder(day) {
|
||||||
|
// incoming day starts from Monday, the symbols start from Sunday
|
||||||
final symbols = DateFormat.EEEE(context.locale.toLanguageTag()).dateSymbols;
|
final symbols = DateFormat.EEEE(context.locale.toLanguageTag()).dateSymbols;
|
||||||
final weekDayString = symbols.WEEKDAYS[day];
|
final weekDayString = symbols.WEEKDAYS[(day + 1) % 7];
|
||||||
return Center(
|
return Center(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: CalendarSize.daysOfWeekInsets,
|
padding: CalendarSize.daysOfWeekInsets,
|
||||||
@ -210,15 +217,21 @@ class _CalendarPageState extends State<CalendarPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
WeekDays _weekdayFromInt(int dayOfWeek) {
|
WeekDays _weekdayFromInt(int dayOfWeek) {
|
||||||
// MonthView places the first day of week on the second column for some reason.
|
// dayOfWeek starts from Sunday, WeekDays starts from Monday
|
||||||
return WeekDays.values[(dayOfWeek + 1) % 7];
|
return WeekDays.values[(dayOfWeek - 1) % 7];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _showEditEventPage(CalendarDayEvent event, BuildContext context) {
|
void showEventDetails({
|
||||||
|
required BuildContext context,
|
||||||
|
required CalendarDayEvent event,
|
||||||
|
required String viewId,
|
||||||
|
required RowCache rowCache,
|
||||||
|
}) {
|
||||||
final dataController = RowController(
|
final dataController = RowController(
|
||||||
rowId: event.eventId,
|
rowId: event.eventId,
|
||||||
viewId: widget.view.id,
|
viewId: viewId,
|
||||||
rowCache: _calendarBloc.rowCache,
|
rowCache: rowCache,
|
||||||
);
|
);
|
||||||
|
|
||||||
FlowyOverlay.show(
|
FlowyOverlay.show(
|
||||||
@ -226,11 +239,10 @@ class _CalendarPageState extends State<CalendarPage> {
|
|||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return RowDetailPage(
|
return RowDetailPage(
|
||||||
cellBuilder: GridCellBuilder(
|
cellBuilder: GridCellBuilder(
|
||||||
cellCache: _calendarBloc.rowCache.cellCache,
|
cellCache: rowCache.cellCache,
|
||||||
),
|
),
|
||||||
dataController: dataController,
|
dataController: dataController,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -216,6 +216,7 @@ class LayoutDateField extends StatelessWidget {
|
|||||||
direction: PopoverDirection.leftWithTopAligned,
|
direction: PopoverDirection.leftWithTopAligned,
|
||||||
constraints: BoxConstraints.loose(const Size(300, 400)),
|
constraints: BoxConstraints.loose(const Size(300, 400)),
|
||||||
mutex: popoverMutex,
|
mutex: popoverMutex,
|
||||||
|
offset: const Offset(-16, 0),
|
||||||
popupBuilder: (context) {
|
popupBuilder: (context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => getIt<DatabasePropertyBloc>(
|
create: (context) => getIt<DatabasePropertyBloc>(
|
||||||
@ -236,9 +237,9 @@ class LayoutDateField extends StatelessWidget {
|
|||||||
onUpdated(fieldInfo.id);
|
onUpdated(fieldInfo.id);
|
||||||
popoverMutex.close();
|
popoverMutex.close();
|
||||||
},
|
},
|
||||||
leftIcon: svgWidget('grid/field/date'),
|
leftIcon: const FlowySvg(name: 'grid/field/date'),
|
||||||
rightIcon: fieldInfo.id == fieldId
|
rightIcon: fieldInfo.id == fieldId
|
||||||
? svgWidget('grid/checkmark')
|
? const FlowySvg(name: 'grid/checkmark')
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -332,12 +333,13 @@ class FirstDayOfWeek extends StatelessWidget {
|
|||||||
direction: PopoverDirection.leftWithTopAligned,
|
direction: PopoverDirection.leftWithTopAligned,
|
||||||
constraints: BoxConstraints.loose(const Size(300, 400)),
|
constraints: BoxConstraints.loose(const Size(300, 400)),
|
||||||
mutex: popoverMutex,
|
mutex: popoverMutex,
|
||||||
|
offset: const Offset(-16, 0),
|
||||||
popupBuilder: (context) {
|
popupBuilder: (context) {
|
||||||
final symbols =
|
final symbols =
|
||||||
DateFormat.EEEE(context.locale.toLanguageTag()).dateSymbols;
|
DateFormat.EEEE(context.locale.toLanguageTag()).dateSymbols;
|
||||||
// starts from sunday
|
// starts from sunday
|
||||||
final items = symbols.WEEKDAYS.asMap().entries.map((entry) {
|
final items = symbols.WEEKDAYS.asMap().entries.map((entry) {
|
||||||
final index = (entry.key - 1) % 7;
|
final index = entry.key;
|
||||||
final string = entry.value;
|
final string = entry.value;
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: GridSize.popoverItemHeight,
|
height: GridSize.popoverItemHeight,
|
||||||
@ -347,8 +349,9 @@ class FirstDayOfWeek extends StatelessWidget {
|
|||||||
onUpdated(index);
|
onUpdated(index);
|
||||||
popoverMutex.close();
|
popoverMutex.close();
|
||||||
},
|
},
|
||||||
rightIcon:
|
rightIcon: firstDayOfWeek == index
|
||||||
firstDayOfWeek == index ? svgWidget('grid/checkmark') : null,
|
? const FlowySvg(name: 'grid/checkmark')
|
||||||
|
: null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
@ -2,8 +2,10 @@ import 'package:appflowy/generated/locale_keys.g.dart';
|
|||||||
import 'package:appflowy/plugins/database_view/application/field/field_controller.dart';
|
import 'package:appflowy/plugins/database_view/application/field/field_controller.dart';
|
||||||
import 'package:appflowy/plugins/database_view/calendar/application/calendar_setting_bloc.dart';
|
import 'package:appflowy/plugins/database_view/calendar/application/calendar_setting_bloc.dart';
|
||||||
import 'package:appflowy/plugins/database_view/grid/presentation/layout/sizes.dart';
|
import 'package:appflowy/plugins/database_view/grid/presentation/layout/sizes.dart';
|
||||||
|
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/toolbar/grid_property.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flowy_infra/image.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/button.dart';
|
import 'package:flowy_infra_ui/style_widget/button.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/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
@ -38,6 +40,11 @@ class CalendarSetting extends StatelessWidget {
|
|||||||
final CalendarSettingAction? action =
|
final CalendarSettingAction? action =
|
||||||
state.selectedAction.foldLeft(null, (previous, action) => action);
|
state.selectedAction.foldLeft(null, (previous, action) => action);
|
||||||
switch (action) {
|
switch (action) {
|
||||||
|
case CalendarSettingAction.properties:
|
||||||
|
return GridPropertyList(
|
||||||
|
viewId: settingContext.viewId,
|
||||||
|
fieldController: settingContext.fieldController,
|
||||||
|
);
|
||||||
case CalendarSettingAction.layout:
|
case CalendarSettingAction.layout:
|
||||||
return CalendarLayoutSetting(
|
return CalendarLayoutSetting(
|
||||||
onUpdated: onUpdated,
|
onUpdated: onUpdated,
|
||||||
@ -78,9 +85,16 @@ class AllCalendarSettings extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _settingItem(BuildContext context, CalendarSettingAction action) {
|
Widget _settingItem(BuildContext context, CalendarSettingAction action) {
|
||||||
|
Widget? icon;
|
||||||
|
if (action.iconName() != null) {
|
||||||
|
icon = FlowySvg(
|
||||||
|
name: action.iconName()!,
|
||||||
|
);
|
||||||
|
}
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: GridSize.popoverItemHeight,
|
height: GridSize.popoverItemHeight,
|
||||||
child: FlowyButton(
|
child: FlowyButton(
|
||||||
|
leftIcon: icon,
|
||||||
text: FlowyText.medium(action.title()),
|
text: FlowyText.medium(action.title()),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context
|
context
|
||||||
@ -93,8 +107,19 @@ class AllCalendarSettings extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension _SettingExtension on CalendarSettingAction {
|
extension _SettingExtension on CalendarSettingAction {
|
||||||
|
String? iconName() {
|
||||||
|
switch (this) {
|
||||||
|
case CalendarSettingAction.properties:
|
||||||
|
return 'grid/setting/properties';
|
||||||
|
case CalendarSettingAction.layout:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String title() {
|
String title() {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
|
case CalendarSettingAction.properties:
|
||||||
|
return LocaleKeys.grid_settings_Properties.tr();
|
||||||
case CalendarSettingAction.layout:
|
case CalendarSettingAction.layout:
|
||||||
return LocaleKeys.grid_settings_layout.tr();
|
return LocaleKeys.grid_settings_layout.tr();
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy/plugins/database_view/calendar/presentation/calendar_page.dart';
|
||||||
import 'package:appflowy/plugins/database_view/grid/presentation/layout/sizes.dart';
|
import 'package:appflowy/plugins/database_view/grid/presentation/layout/sizes.dart';
|
||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
|
import 'package:calendar_view/calendar_view.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';
|
||||||
@ -19,7 +21,8 @@ class CalendarToolbar extends StatelessWidget {
|
|||||||
height: 40,
|
height: 40,
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: const [
|
||||||
|
_UnscheduleEventsButton(),
|
||||||
_SettingButton(),
|
_SettingButton(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -28,25 +31,22 @@ class CalendarToolbar extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _SettingButton extends StatefulWidget {
|
class _SettingButton extends StatefulWidget {
|
||||||
|
const _SettingButton({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<StatefulWidget> createState() => _SettingButtonState();
|
State<StatefulWidget> createState() => _SettingButtonState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SettingButtonState extends State<_SettingButton> {
|
class _SettingButtonState extends State<_SettingButton> {
|
||||||
late PopoverController popoverController;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
popoverController = PopoverController();
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AppFlowyPopover(
|
return AppFlowyPopover(
|
||||||
controller: popoverController,
|
|
||||||
direction: PopoverDirection.bottomWithRightAligned,
|
direction: PopoverDirection.bottomWithRightAligned,
|
||||||
triggerActions: PopoverTriggerFlags.none,
|
|
||||||
constraints: BoxConstraints.loose(const Size(300, 400)),
|
constraints: BoxConstraints.loose(const Size(300, 400)),
|
||||||
margin: EdgeInsets.zero,
|
margin: EdgeInsets.zero,
|
||||||
child: FlowyTextButton(
|
child: FlowyTextButton(
|
||||||
@ -54,7 +54,6 @@ class _SettingButtonState extends State<_SettingButton> {
|
|||||||
fillColor: Colors.transparent,
|
fillColor: Colors.transparent,
|
||||||
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
||||||
padding: GridSize.typeOptionContentInsets,
|
padding: GridSize.typeOptionContentInsets,
|
||||||
onPressed: () => popoverController.show(),
|
|
||||||
),
|
),
|
||||||
popupBuilder: (BuildContext popoverContext) {
|
popupBuilder: (BuildContext popoverContext) {
|
||||||
final bloc = context.watch<CalendarBloc>();
|
final bloc = context.watch<CalendarBloc>();
|
||||||
@ -81,3 +80,100 @@ class _SettingButtonState extends State<_SettingButton> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _UnscheduleEventsButton extends StatefulWidget {
|
||||||
|
const _UnscheduleEventsButton({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_UnscheduleEventsButton> createState() =>
|
||||||
|
_UnscheduleEventsButtonState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UnscheduleEventsButtonState extends State<_UnscheduleEventsButton> {
|
||||||
|
late final PopoverController _controller;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_controller = PopoverController();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocBuilder<CalendarBloc, CalendarState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
final unscheduledEvents = state.allEvents
|
||||||
|
.where((e) => e.date == DateTime.fromMillisecondsSinceEpoch(0))
|
||||||
|
.toList();
|
||||||
|
final viewId = context.read<CalendarBloc>().viewId;
|
||||||
|
final rowCache = context.read<CalendarBloc>().rowCache;
|
||||||
|
return AppFlowyPopover(
|
||||||
|
direction: PopoverDirection.bottomWithCenterAligned,
|
||||||
|
controller: _controller,
|
||||||
|
offset: const Offset(0, 8),
|
||||||
|
child: FlowyTextButton(
|
||||||
|
"${LocaleKeys.calendar_settings_noDateTitle.tr()} (${unscheduledEvents.length})",
|
||||||
|
fillColor: Colors.transparent,
|
||||||
|
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
||||||
|
padding: GridSize.typeOptionContentInsets,
|
||||||
|
),
|
||||||
|
popupBuilder: (context) {
|
||||||
|
if (unscheduledEvents.isEmpty) {
|
||||||
|
return SizedBox(
|
||||||
|
height: GridSize.popoverItemHeight,
|
||||||
|
child: Center(
|
||||||
|
child: FlowyText.medium(
|
||||||
|
LocaleKeys.calendar_settings_emptyNoDate.tr(),
|
||||||
|
color: Theme.of(context).hintColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return ListView.separated(
|
||||||
|
itemBuilder: (context, index) => _UnscheduledEventItem(
|
||||||
|
event: unscheduledEvents[index],
|
||||||
|
onPressed: () {
|
||||||
|
showEventDetails(
|
||||||
|
context: context,
|
||||||
|
event: unscheduledEvents[index].event!,
|
||||||
|
viewId: viewId,
|
||||||
|
rowCache: rowCache,
|
||||||
|
);
|
||||||
|
_controller.close();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
itemCount: unscheduledEvents.length,
|
||||||
|
separatorBuilder: (context, index) =>
|
||||||
|
VSpace(GridSize.typeOptionSeparatorHeight),
|
||||||
|
shrinkWrap: true,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UnscheduledEventItem extends StatelessWidget {
|
||||||
|
final CalendarEventData<CalendarDayEvent> event;
|
||||||
|
final VoidCallback onPressed;
|
||||||
|
const _UnscheduledEventItem({
|
||||||
|
required this.event,
|
||||||
|
required this.onPressed,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SizedBox(
|
||||||
|
height: GridSize.popoverItemHeight,
|
||||||
|
child: FlowyTextButton(
|
||||||
|
event.title,
|
||||||
|
fillColor: Colors.transparent,
|
||||||
|
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
||||||
|
padding: GridSize.typeOptionContentInsets,
|
||||||
|
onPressed: onPressed,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -43,6 +43,7 @@ class RowCardContainer extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
onTap: () => openCard(context),
|
onTap: () => openCard(context),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8),
|
padding: const EdgeInsets.all(8),
|
||||||
|
@ -75,7 +75,7 @@ class DateCellCalendarBloc
|
|||||||
String? time,
|
String? time,
|
||||||
bool? includeTime,
|
bool? includeTime,
|
||||||
}) async {
|
}) async {
|
||||||
// make sure date and time are not updated together from the UI
|
// make sure that not both date and time are updated at the same time
|
||||||
assert(
|
assert(
|
||||||
date == null && time == null ||
|
date == null && time == null ||
|
||||||
date == null && time != null ||
|
date == null && time != null ||
|
||||||
@ -83,7 +83,7 @@ class DateCellCalendarBloc
|
|||||||
);
|
);
|
||||||
String? newTime = time ?? state.time;
|
String? newTime = time ?? state.time;
|
||||||
|
|
||||||
DateTime? newDate = date;
|
DateTime? newDate = _utcToLocalAddTime(date);
|
||||||
if (time != null && time.isNotEmpty) {
|
if (time != null && time.isNotEmpty) {
|
||||||
newDate = state.dateTime ?? DateTime.now();
|
newDate = state.dateTime ?? DateTime.now();
|
||||||
}
|
}
|
||||||
@ -122,6 +122,24 @@ class DateCellCalendarBloc
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DateTime? _utcToLocalAddTime(DateTime? date) {
|
||||||
|
if (date == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final now = DateTime.now();
|
||||||
|
// the incoming date is Utc. this trick converts it into Local
|
||||||
|
// and add the current time, though the time may be overwritten by
|
||||||
|
// explicitly provided time string
|
||||||
|
return DateTime(
|
||||||
|
date.year,
|
||||||
|
date.month,
|
||||||
|
date.day,
|
||||||
|
now.hour,
|
||||||
|
now.minute,
|
||||||
|
now.second,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
String timeFormatPrompt(FlowyError error) {
|
String timeFormatPrompt(FlowyError error) {
|
||||||
String msg = "${LocaleKeys.grid_field_invalidTimeFormat.tr()}.";
|
String msg = "${LocaleKeys.grid_field_invalidTimeFormat.tr()}.";
|
||||||
switch (state.dateTypeOptionPB.timeFormat) {
|
switch (state.dateTypeOptionPB.timeFormat) {
|
||||||
|
@ -115,8 +115,11 @@ class _CellCalendarWidgetState extends State<_CellCalendarWidget> {
|
|||||||
AnimatedSwitcher(
|
AnimatedSwitcher(
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
child: state.includeTime
|
child: state.includeTime
|
||||||
? _TimeTextField(popoverMutex: popoverMutex)
|
? _TimeTextField(
|
||||||
: const SizedBox(),
|
timeStr: state.time,
|
||||||
|
popoverMutex: popoverMutex,
|
||||||
|
)
|
||||||
|
: const SizedBox.shrink(),
|
||||||
),
|
),
|
||||||
const TypeOptionSeparator(spacing: 12.0),
|
const TypeOptionSeparator(spacing: 12.0),
|
||||||
const _IncludeTimeButton(),
|
const _IncludeTimeButton(),
|
||||||
@ -265,9 +268,11 @@ class _IncludeTimeButton extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _TimeTextField extends StatefulWidget {
|
class _TimeTextField extends StatefulWidget {
|
||||||
|
final String? timeStr;
|
||||||
final PopoverMutex popoverMutex;
|
final PopoverMutex popoverMutex;
|
||||||
|
|
||||||
const _TimeTextField({
|
const _TimeTextField({
|
||||||
|
required this.timeStr,
|
||||||
required this.popoverMutex,
|
required this.popoverMutex,
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@ -278,10 +283,12 @@ class _TimeTextField extends StatefulWidget {
|
|||||||
|
|
||||||
class _TimeTextFieldState extends State<_TimeTextField> {
|
class _TimeTextFieldState extends State<_TimeTextField> {
|
||||||
late final FocusNode _focusNode;
|
late final FocusNode _focusNode;
|
||||||
|
late final TextEditingController _textController;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_focusNode = FocusNode();
|
_focusNode = FocusNode();
|
||||||
|
_textController = TextEditingController()..text = widget.timeStr ?? "";
|
||||||
|
|
||||||
_focusNode.addListener(() {
|
_focusNode.addListener(() {
|
||||||
if (_focusNode.hasFocus) {
|
if (_focusNode.hasFocus) {
|
||||||
@ -300,7 +307,8 @@ class _TimeTextFieldState extends State<_TimeTextField> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<DateCellCalendarBloc, DateCellCalendarState>(
|
return BlocConsumer<DateCellCalendarBloc, DateCellCalendarState>(
|
||||||
|
listener: (context, state) => _textController.text = state.time ?? "",
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
@ -310,13 +318,14 @@ class _TimeTextFieldState extends State<_TimeTextField> {
|
|||||||
child: FlowyTextField(
|
child: FlowyTextField(
|
||||||
text: state.time ?? "",
|
text: state.time ?? "",
|
||||||
focusNode: _focusNode,
|
focusNode: _focusNode,
|
||||||
|
controller: _textController,
|
||||||
submitOnLeave: true,
|
submitOnLeave: true,
|
||||||
hintText: state.timeHintText,
|
hintText: state.timeHintText,
|
||||||
errorText: state.timeFormatError,
|
errorText: state.timeFormatError,
|
||||||
onSubmitted: (timeString) {
|
onSubmitted: (timeStr) {
|
||||||
context
|
context
|
||||||
.read<DateCellCalendarBloc>()
|
.read<DateCellCalendarBloc>()
|
||||||
.add(DateCellCalendarEvent.setTime(timeString));
|
.add(DateCellCalendarEvent.setTime(timeStr));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -226,6 +226,9 @@ class _AppFlowyEditorPageState extends State<_AppFlowyEditorPage> {
|
|||||||
if (temporaryNodeTypes.contains(node.type)) {
|
if (temporaryNodeTypes.contains(node.type)) {
|
||||||
transaction.deleteNode(node);
|
transaction.deleteNode(node);
|
||||||
}
|
}
|
||||||
|
if (kCoverType == node.type && !node.path.equals([0])) {
|
||||||
|
transaction.deleteNode(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (transaction.operations.isNotEmpty) {
|
if (transaction.operations.isNotEmpty) {
|
||||||
await editorState.apply(transaction, withUpdateCursor: false);
|
await editorState.apply(transaction, withUpdateCursor: false);
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/emoji_picker/emoji_picker.dart';
|
import 'package:appflowy/workspace/presentation/widgets/emoji_picker/emoji_picker.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/emoji_picker/src/default_emoji_picker_view.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart' hide FlowySvg;
|
||||||
import 'package:appflowy/workspace/presentation/widgets/emoji_picker/src/emoji_view_state.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/button.dart';
|
import 'package:flowy_infra_ui/style_widget/button.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
|
import 'package:flowy_infra/image.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class EmojiPopover extends StatefulWidget {
|
class EmojiPopover extends StatefulWidget {
|
||||||
@ -33,22 +32,21 @@ class _EmojiPopoverState extends State<EmojiPopover> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(15),
|
padding: const EdgeInsets.all(15),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
if (widget.showRemoveButton)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 4.0),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: DeleteButton(onPressed: widget.removeIcon),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
child: EmojiPicker(
|
child: EmojiPicker(
|
||||||
onEmojiSelected: (category, emoji) {
|
onEmojiSelected: (category, emoji) {
|
||||||
widget.onEmojiChanged(emoji);
|
widget.onEmojiChanged(emoji);
|
||||||
},
|
},
|
||||||
customWidget: (Config config, EmojiViewState state) {
|
|
||||||
return Stack(
|
|
||||||
alignment: Alignment.topRight,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
padding: EdgeInsets.only(top: widget.showRemoveButton ? 25 : 0),
|
|
||||||
child: DefaultEmojiPickerView(config, state),
|
|
||||||
),
|
|
||||||
_buildDeleteButtonIfNeed(),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
config: Config(
|
config: Config(
|
||||||
columns: 8,
|
columns: 8,
|
||||||
emojiSizeMax: 28,
|
emojiSizeMax: 28,
|
||||||
@ -61,29 +59,26 @@ class _EmojiPopoverState extends State<EmojiPopover> {
|
|||||||
initCategory: Category.RECENT,
|
initCategory: Category.RECENT,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildDeleteButtonIfNeed() {
|
|
||||||
if (!widget.showRemoveButton) {
|
|
||||||
return const SizedBox();
|
|
||||||
}
|
|
||||||
return FlowyButton(
|
|
||||||
onTap: () => widget.removeIcon(),
|
|
||||||
useIntrinsicWidth: true,
|
|
||||||
text: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
|
||||||
children: [
|
|
||||||
const FlowySvg(name: 'editor/delete'),
|
|
||||||
const SizedBox(
|
|
||||||
width: 5,
|
|
||||||
),
|
|
||||||
FlowyText(
|
|
||||||
LocaleKeys.document_plugins_cover_removeIcon.tr(),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DeleteButton extends StatelessWidget {
|
||||||
|
final VoidCallback onPressed;
|
||||||
|
const DeleteButton({required this.onPressed, Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return FlowyButton(
|
||||||
|
onTap: () => onPressed,
|
||||||
|
useIntrinsicWidth: true,
|
||||||
|
text: FlowyText(
|
||||||
|
LocaleKeys.document_plugins_cover_removeIcon.tr(),
|
||||||
|
),
|
||||||
|
leftIcon: const FlowySvg(name: 'editor/delete'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -29,7 +29,8 @@ void _showEmojiSelectionMenu(
|
|||||||
menuService.dismiss();
|
menuService.dismiss();
|
||||||
|
|
||||||
_emojiSelectionMenu?.remove();
|
_emojiSelectionMenu?.remove();
|
||||||
_emojiSelectionMenu = OverlayEntry(builder: (context) {
|
_emojiSelectionMenu = OverlayEntry(
|
||||||
|
builder: (context) {
|
||||||
return Positioned(
|
return Positioned(
|
||||||
top: alignment == Alignment.bottomLeft ? offset.dy : null,
|
top: alignment == Alignment.bottomLeft ? offset.dy : null,
|
||||||
bottom: alignment == Alignment.topLeft ? offset.dy : null,
|
bottom: alignment == Alignment.topLeft ? offset.dy : null,
|
||||||
@ -48,10 +49,12 @@ void _showEmojiSelectionMenu(
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},);
|
},
|
||||||
|
);
|
||||||
|
|
||||||
Overlay.of(context).insert(_emojiSelectionMenu!);
|
Overlay.of(context).insert(_emojiSelectionMenu!);
|
||||||
|
|
||||||
|
_editorState = editorState;
|
||||||
editorState.service.selectionService.currentSelection
|
editorState.service.selectionService.currentSelection
|
||||||
.addListener(_dismissEmojiSelectionMenu);
|
.addListener(_dismissEmojiSelectionMenu);
|
||||||
}
|
}
|
||||||
@ -62,6 +65,7 @@ void _dismissEmojiSelectionMenu() {
|
|||||||
|
|
||||||
_editorState?.service.selectionService.currentSelection
|
_editorState?.service.selectionService.currentSelection
|
||||||
.removeListener(_dismissEmojiSelectionMenu);
|
.removeListener(_dismissEmojiSelectionMenu);
|
||||||
|
_editorState?.service.keyboardService?.enable();
|
||||||
_editorState = null;
|
_editorState = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +61,10 @@ class ViewSection extends StatelessWidget {
|
|||||||
.add(ViewSectionEvent.moveView(oldIndex, index));
|
.add(ViewSectionEvent.moveView(oldIndex, index));
|
||||||
},
|
},
|
||||||
ignorePrimaryScrollController: true,
|
ignorePrimaryScrollController: true,
|
||||||
|
buildDraggableFeedback: (context, constraints, child) => ConstrainedBox(
|
||||||
|
constraints: constraints,
|
||||||
|
child: Material(color: Colors.transparent, child: child),
|
||||||
|
),
|
||||||
children: children,
|
children: children,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -149,6 +149,8 @@ class HomeMenu extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
proxyDecorator: (child, index, animation) =>
|
||||||
|
Material(color: Colors.transparent, child: child),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -592,6 +592,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.appflowy.macos;
|
PRODUCT_BUNDLE_IDENTIFIER = com.appflowy.macos;
|
||||||
PRODUCT_NAME = AppFlowy;
|
PRODUCT_NAME = AppFlowy;
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
@ -132,6 +132,21 @@ class FlowyHoverContainer extends StatelessWidget {
|
|||||||
width: style.borderWidth,
|
width: style.borderWidth,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
final textTheme = theme.textTheme;
|
||||||
|
final iconTheme = theme.iconTheme;
|
||||||
|
// override text's theme with foregroundColorOnHover when it is hovered
|
||||||
|
final hoverTheme = theme.copyWith(
|
||||||
|
textTheme: textTheme.copyWith(
|
||||||
|
bodyMedium: textTheme.bodyMedium?.copyWith(
|
||||||
|
color: style.foregroundColorOnHover ?? theme.colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
iconTheme: iconTheme.copyWith(
|
||||||
|
color: style.foregroundColorOnHover ?? theme.colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
margin: style.contentMargin,
|
margin: style.contentMargin,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
@ -139,19 +154,8 @@ class FlowyHoverContainer extends StatelessWidget {
|
|||||||
color: style.hoverColor ?? Theme.of(context).colorScheme.secondary,
|
color: style.hoverColor ?? Theme.of(context).colorScheme.secondary,
|
||||||
borderRadius: style.borderRadius,
|
borderRadius: style.borderRadius,
|
||||||
),
|
),
|
||||||
child:
|
child: Theme(
|
||||||
//override text's theme with foregroundColorOnHover when it is hovered
|
data: hoverTheme,
|
||||||
Theme(
|
|
||||||
data: Theme.of(context).copyWith(
|
|
||||||
textTheme: Theme.of(context).textTheme.copyWith(
|
|
||||||
bodyMedium: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
|
||||||
color: style.foregroundColorOnHover ??
|
|
||||||
Theme.of(context).colorScheme.onSurface),
|
|
||||||
),
|
|
||||||
iconTheme: Theme.of(context).iconTheme.copyWith(
|
|
||||||
color: style.foregroundColorOnHover ??
|
|
||||||
Theme.of(context).colorScheme.onSurface),
|
|
||||||
),
|
|
||||||
child: child,
|
child: child,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -45,10 +45,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: appflowy_editor
|
name: appflowy_editor
|
||||||
sha256: a1dbca3d7d33f4669f1d44bfa1e06b6646f46726c219921b8a59d9ee22bf252d
|
sha256: "6f7d2b0b54ca1049cb396229549d228b5bbd7ea6d09f1f7325a20db2d7586a5f"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.9"
|
version: "0.1.12"
|
||||||
appflowy_popover:
|
appflowy_popover:
|
||||||
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.1.2
|
version: 0.1.5
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.19.0 <3.0.0"
|
sdk: ">=2.19.0 <3.0.0"
|
||||||
@ -42,7 +42,7 @@ dependencies:
|
|||||||
git:
|
git:
|
||||||
url: https://github.com/AppFlowy-IO/appflowy-board.git
|
url: https://github.com/AppFlowy-IO/appflowy-board.git
|
||||||
ref: a183c57
|
ref: a183c57
|
||||||
appflowy_editor: ^0.1.9
|
appflowy_editor: ^0.1.12
|
||||||
appflowy_popover:
|
appflowy_popover:
|
||||||
path: packages/appflowy_popover
|
path: packages/appflowy_popover
|
||||||
|
|
||||||
|
@ -216,7 +216,17 @@ impl TypeOptionCellDataCompare for NumberTypeOptionPB {
|
|||||||
cell_data: &<Self as TypeOption>::CellData,
|
cell_data: &<Self as TypeOption>::CellData,
|
||||||
other_cell_data: &<Self as TypeOption>::CellData,
|
other_cell_data: &<Self as TypeOption>::CellData,
|
||||||
) -> Ordering {
|
) -> Ordering {
|
||||||
cell_data.0.cmp(&other_cell_data.0)
|
let left = NumberCellData::from_format_str(&cell_data.0, self.sign_positive, &self.format);
|
||||||
|
let right =
|
||||||
|
NumberCellData::from_format_str(&other_cell_data.0, self.sign_positive, &self.format);
|
||||||
|
match (left, right) {
|
||||||
|
(Ok(left), Ok(right)) => {
|
||||||
|
return left.decimal().cmp(&right.decimal());
|
||||||
|
},
|
||||||
|
(Ok(_), Err(_)) => Ordering::Greater,
|
||||||
|
(Err(_), Ok(_)) => Ordering::Less,
|
||||||
|
(Err(_), Err(_)) => Ordering::Equal,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl std::default::Default for NumberTypeOptionPB {
|
impl std::default::Default for NumberTypeOptionPB {
|
||||||
|
@ -161,7 +161,7 @@ pub fn make_test_grid() -> BuildDatabaseContext {
|
|||||||
for field_type in FieldType::iter() {
|
for field_type in FieldType::iter() {
|
||||||
match field_type {
|
match field_type {
|
||||||
FieldType::RichText => row_builder.insert_text_cell("DA"),
|
FieldType::RichText => row_builder.insert_text_cell("DA"),
|
||||||
FieldType::Number => row_builder.insert_number_cell("4"),
|
FieldType::Number => row_builder.insert_number_cell("14"),
|
||||||
FieldType::DateTime => row_builder.insert_date_cell("1668704685"),
|
FieldType::DateTime => row_builder.insert_date_cell("1668704685"),
|
||||||
FieldType::SingleSelect => {
|
FieldType::SingleSelect => {
|
||||||
row_builder.insert_single_select_cell(|mut options| options.remove(0))
|
row_builder.insert_single_select_cell(|mut options| options.remove(0))
|
||||||
|
@ -212,7 +212,7 @@ async fn sort_number_by_descending_test() {
|
|||||||
let scripts = vec![
|
let scripts = vec![
|
||||||
AssertCellContentOrder {
|
AssertCellContentOrder {
|
||||||
field_id: number_field.id.clone(),
|
field_id: number_field.id.clone(),
|
||||||
orders: vec!["$1", "$2", "$3", "$4", "", "$5"],
|
orders: vec!["$1", "$2", "$3", "$14", "", "$5"],
|
||||||
},
|
},
|
||||||
InsertSort {
|
InsertSort {
|
||||||
field_rev: number_field.clone(),
|
field_rev: number_field.clone(),
|
||||||
@ -220,7 +220,7 @@ async fn sort_number_by_descending_test() {
|
|||||||
},
|
},
|
||||||
AssertCellContentOrder {
|
AssertCellContentOrder {
|
||||||
field_id: number_field.id.clone(),
|
field_id: number_field.id.clone(),
|
||||||
orders: vec!["$5", "$4", "$3", "$2", "$1", ""],
|
orders: vec!["$14", "$5", "$3", "$2", "$1", ""],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
test.run_scripts(scripts).await;
|
test.run_scripts(scripts).await;
|
||||||
|
@ -2,175 +2,78 @@
|
|||||||
"document": {
|
"document": {
|
||||||
"type": "editor",
|
"type": "editor",
|
||||||
"children": [
|
"children": [
|
||||||
|
{ "type": "cover" },
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"attributes": {
|
"attributes": { "subtype": "heading", "heading": "h1" },
|
||||||
"subtype": "heading",
|
"delta": [{ "insert": "Welcome to AppFlowy!" }]
|
||||||
"heading": "h1"
|
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"attributes": { "subtype": "heading", "heading": "h2" },
|
||||||
|
"delta": [{ "insert": "Here are the basics" }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"attributes": { "subtype": "checkbox", "checkbox": null },
|
||||||
|
"delta": [{ "insert": "Click anywhere and just start typing." }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"attributes": { "subtype": "checkbox", "checkbox": false },
|
||||||
"delta": [
|
"delta": [
|
||||||
{
|
{
|
||||||
"insert": "🌟 Welcome to AppFlowy!"
|
"insert": "Highlight ",
|
||||||
}
|
"attributes": { "backgroundColor": "0x4dffeb3b" }
|
||||||
|
},
|
||||||
|
{ "insert": "any text, and use the editing menu to " },
|
||||||
|
{ "insert": "style", "attributes": { "italic": true } },
|
||||||
|
{ "insert": " " },
|
||||||
|
{ "insert": "your", "attributes": { "bold": true } },
|
||||||
|
{ "insert": " " },
|
||||||
|
{ "insert": "writing", "attributes": { "underline": true } },
|
||||||
|
{ "insert": " " },
|
||||||
|
{ "insert": "however", "attributes": { "code": true } },
|
||||||
|
{ "insert": " you " },
|
||||||
|
{ "insert": "like.", "attributes": { "strikethrough": true } }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"attributes": {
|
"attributes": { "subtype": "checkbox", "checkbox": null },
|
||||||
"subtype": "heading",
|
|
||||||
"heading": "h2"
|
|
||||||
},
|
|
||||||
"delta": [
|
"delta": [
|
||||||
{
|
{ "insert": "As soon as you type " },
|
||||||
"insert": "Here are the basics"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"attributes": {
|
|
||||||
"subtype": "checkbox",
|
|
||||||
"checkbox": null
|
|
||||||
},
|
|
||||||
"delta": [
|
|
||||||
{
|
|
||||||
"insert": "Click anywhere and just start typing."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"attributes": {
|
|
||||||
"subtype": "checkbox",
|
|
||||||
"checkbox": null
|
|
||||||
},
|
|
||||||
"delta": [
|
|
||||||
{
|
|
||||||
"insert": "Highlight",
|
|
||||||
"attributes": {
|
|
||||||
"backgroundColor": "0x6000BCF0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"insert": " any text, and use the editing menu to "
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"insert": "style",
|
|
||||||
"attributes": {
|
|
||||||
"italic": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"insert": " "
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"insert": "your",
|
|
||||||
"attributes": {
|
|
||||||
"bold": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"insert": " "
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"insert": "writing",
|
|
||||||
"attributes": {
|
|
||||||
"underline": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"insert": " "
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"insert": "however",
|
|
||||||
"attributes": {
|
|
||||||
"code": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"insert": " you "
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"insert": "like.",
|
|
||||||
"attributes": {
|
|
||||||
"strikethrough": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"attributes": {
|
|
||||||
"subtype": "checkbox",
|
|
||||||
"checkbox": null
|
|
||||||
},
|
|
||||||
"delta": [
|
|
||||||
{
|
|
||||||
"insert": "As soon as you type "
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"insert": "/",
|
"insert": "/",
|
||||||
"attributes": {
|
"attributes": { "code": true, "color": "0xff00b5ff" }
|
||||||
"code": true
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
{ "insert": " a menu will pop up. Select " },
|
||||||
{
|
{
|
||||||
"insert": " a menu will pop up. Select different types of content blocks you can add."
|
"insert": "different types",
|
||||||
}
|
"attributes": { "backgroundColor": "0x4d9c27b0" }
|
||||||
|
},
|
||||||
|
{ "insert": " of content blocks you can add." }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"attributes": {
|
"attributes": { "subtype": "checkbox", "checkbox": null },
|
||||||
"subtype": "checkbox",
|
|
||||||
"checkbox": null
|
|
||||||
},
|
|
||||||
"delta": [
|
"delta": [
|
||||||
{
|
{ "insert": "Type " },
|
||||||
"insert": "Type "
|
{ "insert": "/", "attributes": { "code": true } },
|
||||||
},
|
{ "insert": " followed by " },
|
||||||
{
|
{ "insert": "/bullet", "attributes": { "code": true } },
|
||||||
"insert": "/",
|
{ "insert": " or " },
|
||||||
"attributes": {
|
{ "insert": "/num", "attributes": { "code": true } },
|
||||||
"code": true
|
{ "insert": " to create a list.", "attributes": { "code": false } }
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"insert": " followed by "
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"insert": "/bullet",
|
|
||||||
"attributes": {
|
|
||||||
"code": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"insert": " or "
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"insert": "/c.",
|
|
||||||
"attributes": {
|
|
||||||
"code": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"attributes": {
|
"attributes": { "subtype": "checkbox", "checkbox": true },
|
||||||
"subtype": "checkbox",
|
|
||||||
"checkbox": true
|
|
||||||
},
|
|
||||||
"delta": [
|
"delta": [
|
||||||
{
|
{ "insert": "Click " },
|
||||||
"insert": "Click "
|
{ "insert": "+ New Page ", "attributes": { "code": true } },
|
||||||
},
|
|
||||||
{
|
|
||||||
"insert": "+ New Page ",
|
|
||||||
"attributes": {
|
|
||||||
"code": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"insert": "button at the bottom of your sidebar to add a new page."
|
"insert": "button at the bottom of your sidebar to add a new page."
|
||||||
}
|
}
|
||||||
@ -178,32 +81,24 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"attributes": {
|
"attributes": { "subtype": "checkbox", "checkbox": null },
|
||||||
"subtype": "checkbox",
|
|
||||||
"checkbox": null
|
|
||||||
},
|
|
||||||
"delta": [
|
"delta": [
|
||||||
{
|
{ "insert": "Click " },
|
||||||
"insert": "Click "
|
{ "insert": "+", "attributes": { "code": true } },
|
||||||
},
|
{ "insert": " next to any page title in the sidebar to " },
|
||||||
{
|
{ "insert": "quickly", "attributes": { "color": "0xff8427e0" } },
|
||||||
"insert": "+",
|
{ "insert": " add a new subpage, " },
|
||||||
"attributes": {
|
{ "insert": "Document", "attributes": { "code": true } },
|
||||||
"code": true
|
{ "insert": ", ", "attributes": { "code": false } },
|
||||||
}
|
{ "insert": "Grid", "attributes": { "code": true } },
|
||||||
},
|
{ "insert": ", or ", "attributes": { "code": false } },
|
||||||
{
|
{ "insert": "Kanban Board", "attributes": { "code": true } },
|
||||||
"insert": " next to any page title in the sidebar to quickly add a new subpage."
|
{ "insert": ".", "attributes": { "code": false } }
|
||||||
}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{ "type": "text", "delta": [] },
|
||||||
"type": "text",
|
{ "type": "divider" },
|
||||||
"attributes": {
|
{ "type": "text", "attributes": { "checkbox": null }, "delta": [] },
|
||||||
"checkbox": null
|
|
||||||
},
|
|
||||||
"delta": []
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"attributes": {
|
"attributes": {
|
||||||
@ -211,11 +106,7 @@
|
|||||||
"checkbox": null,
|
"checkbox": null,
|
||||||
"heading": "h2"
|
"heading": "h2"
|
||||||
},
|
},
|
||||||
"delta": [
|
"delta": [{ "insert": "Keyboard shortcuts, markdown, and code block" }]
|
||||||
{
|
|
||||||
"insert": "Markdown"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@ -225,98 +116,64 @@
|
|||||||
"heading": null
|
"heading": null
|
||||||
},
|
},
|
||||||
"delta": [
|
"delta": [
|
||||||
|
{ "insert": "Keyboard shortcuts " },
|
||||||
{
|
{
|
||||||
"insert": "Heading "
|
"insert": "guide",
|
||||||
|
"attributes": {
|
||||||
|
"href": "https://appflowy.gitbook.io/docs/essential-documentation/shortcuts"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{ "retain": 1, "attributes": { "strikethrough": true } }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"subtype": "number-list",
|
"subtype": "number-list",
|
||||||
"number": 2
|
"number": 2,
|
||||||
|
"heading": null
|
||||||
},
|
},
|
||||||
"delta": [
|
"delta": [
|
||||||
|
{ "insert": "Markdown " },
|
||||||
{
|
{
|
||||||
"insert": "bold text",
|
"insert": "reference",
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"bold": true,
|
"href": "https://appflowy.gitbook.io/docs/essential-documentation/markdown"
|
||||||
"defaultFormatting": true
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{ "retain": 1, "attributes": { "strikethrough": true } }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"attributes": { "number": 3, "subtype": "number-list" },
|
||||||
|
"delta": [
|
||||||
|
{ "insert": "Type " },
|
||||||
|
{ "insert": "/code", "attributes": { "code": true } },
|
||||||
|
{
|
||||||
|
"insert": " to insert a code block",
|
||||||
|
"attributes": { "code": false }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"subtype": "number-list",
|
"subtype": "code_block",
|
||||||
"number": 3
|
"number": 3,
|
||||||
|
"heading": null,
|
||||||
|
"number-list": null,
|
||||||
|
"theme": "vs",
|
||||||
|
"language": "rust"
|
||||||
},
|
},
|
||||||
"delta": [
|
"delta": [
|
||||||
{
|
{
|
||||||
"insert": "italicized text",
|
"insert": "// This is the main function.\nfn main() {\n // Print text to the console.\n println!(\"Hello World!\");\n}"
|
||||||
"attributes": {
|
},
|
||||||
"italic": true
|
{ "retain": 1, "attributes": { "strikethrough": true } }
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{ "type": "text", "attributes": { "checkbox": null }, "delta": [] },
|
||||||
"type": "text",
|
|
||||||
"attributes": {
|
|
||||||
"subtype": "number-list",
|
|
||||||
"number": 4,
|
|
||||||
"number-list": null
|
|
||||||
},
|
|
||||||
"delta": [
|
|
||||||
{
|
|
||||||
"insert": "Ordered List"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"attributes": {
|
|
||||||
"number": 5,
|
|
||||||
"subtype": "number-list"
|
|
||||||
},
|
|
||||||
"delta": [
|
|
||||||
{
|
|
||||||
"insert": "code",
|
|
||||||
"attributes": {
|
|
||||||
"code": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"attributes": {
|
|
||||||
"number": 6,
|
|
||||||
"subtype": "number-list"
|
|
||||||
},
|
|
||||||
"delta": [
|
|
||||||
{
|
|
||||||
"insert": "Strikethrough",
|
|
||||||
"attributes": {
|
|
||||||
"strikethrough": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"retain": 1,
|
|
||||||
"attributes": {
|
|
||||||
"strikethrough": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"attributes": {
|
|
||||||
"checkbox": null
|
|
||||||
},
|
|
||||||
"delta": []
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"attributes": {
|
"attributes": {
|
||||||
@ -324,54 +181,30 @@
|
|||||||
"checkbox": null,
|
"checkbox": null,
|
||||||
"heading": "h2"
|
"heading": "h2"
|
||||||
},
|
},
|
||||||
"delta": [
|
"delta": [{ "insert": "Have a question❓" }]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"insert": "Have a question?"
|
"type": "text",
|
||||||
}
|
"attributes": { "subtype": "quote" },
|
||||||
|
"delta": [
|
||||||
|
{ "insert": "Click " },
|
||||||
|
{ "insert": "?", "attributes": { "code": true } },
|
||||||
|
{ "insert": " at the bottom right for help and support." }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{ "type": "text", "delta": [] },
|
||||||
|
{
|
||||||
|
"type": "callout",
|
||||||
|
"children": [
|
||||||
|
{ "type": "text", "delta": [] },
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"attributes": {
|
"attributes": { "subtype": "heading", "heading": "h2" },
|
||||||
"subtype": "quote"
|
"delta": [{ "insert": "Like AppFlowy? Follow us:" }]
|
||||||
},
|
|
||||||
"delta": [
|
|
||||||
{
|
|
||||||
"insert": "Click "
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"insert": "?",
|
|
||||||
"attributes": {
|
|
||||||
"code": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"insert": " at the bottom right for help and support."
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"delta": []
|
"attributes": { "subtype": "bulleted-list" },
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"attributes": {
|
|
||||||
"subtype": "heading",
|
|
||||||
"heading": "h2"
|
|
||||||
},
|
|
||||||
"delta": [
|
|
||||||
{
|
|
||||||
"insert": "Like AppFlowy? Follow us:"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"attributes": {
|
|
||||||
"subtype": "bulleted-list",
|
|
||||||
"quote": null
|
|
||||||
},
|
|
||||||
"delta": [
|
"delta": [
|
||||||
{
|
{
|
||||||
"insert": "GitHub",
|
"insert": "GitHub",
|
||||||
@ -383,35 +216,37 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"attributes": {
|
"attributes": { "subtype": "bulleted-list" },
|
||||||
"subtype": "bulleted-list"
|
|
||||||
},
|
|
||||||
"delta": [
|
"delta": [
|
||||||
{
|
{
|
||||||
"insert": "Twitter: @appflowy"
|
"insert": "Twitter",
|
||||||
}
|
"attributes": { "href": "https://twitter.com/appflowy" }
|
||||||
|
},
|
||||||
|
{ "insert": ": @appflowy" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"attributes": {
|
"attributes": { "subtype": "bulleted-list" },
|
||||||
"subtype": "bulleted-list"
|
|
||||||
},
|
|
||||||
"delta": [
|
"delta": [
|
||||||
{
|
{
|
||||||
"insert": "Newsletter",
|
"insert": "Newsletter",
|
||||||
"attributes": {
|
"attributes": { "href": "https://blog-appflowy.ghost.io/" }
|
||||||
"href": "https://blog-appflowy.ghost.io/"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": { "emoji": "🥰" }
|
||||||
|
},
|
||||||
|
{ "type": "text", "delta": [] },
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"attributes": { "subtype": null, "heading": null },
|
||||||
|
"delta": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"attributes": {
|
"attributes": { "subtype": null, "heading": null },
|
||||||
"subtype": null,
|
|
||||||
"heading": null
|
|
||||||
},
|
|
||||||
"delta": []
|
"delta": []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -23,6 +23,11 @@ args[1]: The appflowy version to be built (github ref_name).
|
|||||||
assert(await repositoryRoot.exists(),
|
assert(await repositoryRoot.exists(),
|
||||||
'$repositoryRoot is an invalid directory. Please try again with a valid directory.\n\n$help');
|
'$repositoryRoot is an invalid directory. Please try again with a valid directory.\n\n$help');
|
||||||
final appVersion = args[1];
|
final appVersion = args[1];
|
||||||
await _BuildTool(repositoryRoot: repositoryRoot.path, appVersion: appVersion)
|
String? arch;
|
||||||
.run();
|
if (args.length > 2) arch = args[2];
|
||||||
|
await _BuildTool(
|
||||||
|
repositoryRoot: repositoryRoot.path,
|
||||||
|
appVersion: appVersion,
|
||||||
|
arch: arch,
|
||||||
|
).run();
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,12 @@ class _BuildTool {
|
|||||||
const _BuildTool({
|
const _BuildTool({
|
||||||
required this.repositoryRoot,
|
required this.repositoryRoot,
|
||||||
required this.appVersion,
|
required this.appVersion,
|
||||||
|
this.arch,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String repositoryRoot;
|
final String repositoryRoot;
|
||||||
final String appVersion;
|
final String appVersion;
|
||||||
|
final String? arch;
|
||||||
|
|
||||||
String get projectRoot =>
|
String get projectRoot =>
|
||||||
[repositoryRoot, 'appflowy_flutter'].join(Platform.pathSeparator);
|
[repositoryRoot, 'appflowy_flutter'].join(Platform.pathSeparator);
|
||||||
@ -30,8 +32,9 @@ class _BuildTool {
|
|||||||
|
|
||||||
Future<String> get _commandForOS async {
|
Future<String> get _commandForOS async {
|
||||||
// Check the operating system and CPU architecture
|
// Check the operating system and CPU architecture
|
||||||
var os = Platform.operatingSystem;
|
final os = Platform.operatingSystem;
|
||||||
var arch = Platform.isMacOS ? await _architecture : Platform.localHostname;
|
final arch = this.arch ??
|
||||||
|
(Platform.isMacOS ? await _architecture : Platform.localHostname);
|
||||||
|
|
||||||
// Determine the appropriate command based on the OS and architecture
|
// Determine the appropriate command based on the OS and architecture
|
||||||
if (os == 'windows') {
|
if (os == 'windows') {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
[Setup]
|
[Setup]
|
||||||
AppName=AppFlowy
|
AppName=AppFlowy
|
||||||
AppVersion={#AppVersion}
|
AppVersion={#AppVersion}
|
||||||
|
AppPublisher=AppFlowy-IO
|
||||||
WizardStyle=modern
|
WizardStyle=modern
|
||||||
Compression=lzma2
|
Compression=lzma2
|
||||||
SolidCompression=yes
|
SolidCompression=yes
|
||||||
@ -9,8 +10,8 @@ DefaultGroupName=AppFlowy
|
|||||||
SetupIconFile=flowy_logo.ico
|
SetupIconFile=flowy_logo.ico
|
||||||
UninstallDisplayIcon={app}\AppFlowy.exe
|
UninstallDisplayIcon={app}\AppFlowy.exe
|
||||||
UninstallDisplayName=AppFlowy
|
UninstallDisplayName=AppFlowy
|
||||||
AppPublisher=AppFlowy-IO
|
|
||||||
VersionInfoVersion={#AppVersion}
|
VersionInfoVersion={#AppVersion}
|
||||||
|
UsePreviousAppDir=no
|
||||||
|
|
||||||
[Files]
|
[Files]
|
||||||
Source: "AppFlowy\AppFlowy.exe";DestDir: "{app}";DestName: "AppFlowy.exe"
|
Source: "AppFlowy\AppFlowy.exe";DestDir: "{app}";DestName: "AppFlowy.exe"
|
||||||
@ -18,4 +19,5 @@ Source: "AppFlowy\*";DestDir: "{app}"
|
|||||||
Source: "AppFlowy\data\*";DestDir: "{app}\data\"; Flags: recursesubdirs
|
Source: "AppFlowy\data\*";DestDir: "{app}\data\"; Flags: recursesubdirs
|
||||||
|
|
||||||
[Icons]
|
[Icons]
|
||||||
Name: "{group}\AppFlowy";Filename: "{app}\AppFlowy.exe"
|
Name: "{userdesktop}\AppFlowy"; Filename: "{app}\AppFlowy.exe"
|
||||||
|
Name: "{group}\AppFlowy"; Filename: "{app}\AppFlowy.exe"
|
Reference in New Issue
Block a user