mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
Merge branch 'upstream-main' into feat/tauri-kanban
# Conflicts: # frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts
This commit is contained in:
commit
745ee264c8
@ -159,8 +159,11 @@ class DatabaseController {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Either<Unit, FlowyError>> moveRow(RowPB fromRow,
|
Future<Either<Unit, FlowyError>> moveRow({
|
||||||
{RowPB? toRow, String? groupId}) {
|
required RowPB fromRow,
|
||||||
|
required String groupId,
|
||||||
|
RowPB? toRow,
|
||||||
|
}) {
|
||||||
return _databaseViewBackendSvc.moveRow(
|
return _databaseViewBackendSvc.moveRow(
|
||||||
fromRowId: fromRow.id,
|
fromRowId: fromRow.id,
|
||||||
toGroupId: groupId,
|
toGroupId: groupId,
|
||||||
|
@ -46,15 +46,13 @@ class DatabaseViewBackendService {
|
|||||||
|
|
||||||
Future<Either<Unit, FlowyError>> moveRow({
|
Future<Either<Unit, FlowyError>> moveRow({
|
||||||
required String fromRowId,
|
required String fromRowId,
|
||||||
required String? toGroupId,
|
required String toGroupId,
|
||||||
required String? toRowId,
|
String? toRowId,
|
||||||
}) {
|
}) {
|
||||||
var payload = MoveGroupRowPayloadPB.create()
|
var payload = MoveGroupRowPayloadPB.create()
|
||||||
..viewId = viewId
|
..viewId = viewId
|
||||||
..fromRowId = fromRowId;
|
..fromRowId = fromRowId
|
||||||
if (toGroupId != null) {
|
..toGroupId = toGroupId;
|
||||||
payload.toGroupId = toGroupId;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toRowId != null) {
|
if (toRowId != null) {
|
||||||
payload.toRowId = toRowId;
|
payload.toRowId = toRowId;
|
||||||
|
@ -54,7 +54,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
|||||||
final toRow = groupControllers[groupId]?.rowAtIndex(toIndex);
|
final toRow = groupControllers[groupId]?.rowAtIndex(toIndex);
|
||||||
if (fromRow != null) {
|
if (fromRow != null) {
|
||||||
_databaseController.moveRow(
|
_databaseController.moveRow(
|
||||||
fromRow,
|
fromRow: fromRow,
|
||||||
toRow: toRow,
|
toRow: toRow,
|
||||||
groupId: groupId,
|
groupId: groupId,
|
||||||
);
|
);
|
||||||
@ -70,7 +70,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
|||||||
final toRow = groupControllers[toGroupId]?.rowAtIndex(toIndex);
|
final toRow = groupControllers[toGroupId]?.rowAtIndex(toIndex);
|
||||||
if (fromRow != null) {
|
if (fromRow != null) {
|
||||||
_databaseController.moveRow(
|
_databaseController.moveRow(
|
||||||
fromRow,
|
fromRow: fromRow,
|
||||||
toRow: toRow,
|
toRow: toRow,
|
||||||
groupId: toGroupId,
|
groupId: toGroupId,
|
||||||
);
|
);
|
||||||
|
@ -65,6 +65,7 @@ class _SettingButtonState extends State<_SettingButton> {
|
|||||||
return AppFlowyPopover(
|
return AppFlowyPopover(
|
||||||
controller: popoverController,
|
controller: popoverController,
|
||||||
direction: PopoverDirection.leftWithTopAligned,
|
direction: PopoverDirection.leftWithTopAligned,
|
||||||
|
offset: const Offset(-8, 0),
|
||||||
triggerActions: PopoverTriggerFlags.none,
|
triggerActions: PopoverTriggerFlags.none,
|
||||||
constraints: BoxConstraints.loose(const Size(260, 400)),
|
constraints: BoxConstraints.loose(const Size(260, 400)),
|
||||||
margin: EdgeInsets.zero,
|
margin: EdgeInsets.zero,
|
||||||
|
@ -87,7 +87,7 @@ class _SwitchFieldButton extends StatelessWidget {
|
|||||||
asBarrier: true,
|
asBarrier: true,
|
||||||
triggerActions: PopoverTriggerFlags.click,
|
triggerActions: PopoverTriggerFlags.click,
|
||||||
mutex: popoverMutex,
|
mutex: popoverMutex,
|
||||||
offset: const Offset(20, 0),
|
offset: const Offset(8, 0),
|
||||||
popupBuilder: (popOverContext) {
|
popupBuilder: (popOverContext) {
|
||||||
return FieldTypeList(onSelectField: (newFieldType) {
|
return FieldTypeList(onSelectField: (newFieldType) {
|
||||||
context
|
context
|
||||||
|
@ -80,7 +80,7 @@ class DateTypeOptionWidget extends TypeOptionWidget {
|
|||||||
mutex: popoverMutex,
|
mutex: popoverMutex,
|
||||||
asBarrier: true,
|
asBarrier: true,
|
||||||
triggerActions: PopoverTriggerFlags.hover | PopoverTriggerFlags.click,
|
triggerActions: PopoverTriggerFlags.hover | PopoverTriggerFlags.click,
|
||||||
offset: const Offset(20, 0),
|
offset: const Offset(8, 0),
|
||||||
constraints: BoxConstraints.loose(const Size(460, 440)),
|
constraints: BoxConstraints.loose(const Size(460, 440)),
|
||||||
popupBuilder: (popoverContext) {
|
popupBuilder: (popoverContext) {
|
||||||
return DateFormatList(
|
return DateFormatList(
|
||||||
@ -107,7 +107,7 @@ class DateTypeOptionWidget extends TypeOptionWidget {
|
|||||||
mutex: popoverMutex,
|
mutex: popoverMutex,
|
||||||
asBarrier: true,
|
asBarrier: true,
|
||||||
triggerActions: PopoverTriggerFlags.hover | PopoverTriggerFlags.click,
|
triggerActions: PopoverTriggerFlags.hover | PopoverTriggerFlags.click,
|
||||||
offset: const Offset(20, 0),
|
offset: const Offset(8, 0),
|
||||||
constraints: BoxConstraints.loose(const Size(460, 440)),
|
constraints: BoxConstraints.loose(const Size(460, 440)),
|
||||||
popupBuilder: (BuildContext popoverContext) {
|
popupBuilder: (BuildContext popoverContext) {
|
||||||
return TimeFormatList(
|
return TimeFormatList(
|
||||||
|
@ -77,7 +77,7 @@ class NumberTypeOptionWidget extends TypeOptionWidget {
|
|||||||
mutex: popoverMutex,
|
mutex: popoverMutex,
|
||||||
triggerActions:
|
triggerActions:
|
||||||
PopoverTriggerFlags.hover | PopoverTriggerFlags.click,
|
PopoverTriggerFlags.hover | PopoverTriggerFlags.click,
|
||||||
offset: const Offset(20, 0),
|
offset: const Offset(8, 0),
|
||||||
constraints: BoxConstraints.loose(const Size(460, 440)),
|
constraints: BoxConstraints.loose(const Size(460, 440)),
|
||||||
margin: EdgeInsets.zero,
|
margin: EdgeInsets.zero,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
|
@ -203,7 +203,7 @@ class _OptionCellState extends State<_OptionCell> {
|
|||||||
return AppFlowyPopover(
|
return AppFlowyPopover(
|
||||||
controller: _popoverController,
|
controller: _popoverController,
|
||||||
mutex: widget.popoverMutex,
|
mutex: widget.popoverMutex,
|
||||||
offset: const Offset(20, 0),
|
offset: const Offset(8, 0),
|
||||||
margin: EdgeInsets.zero,
|
margin: EdgeInsets.zero,
|
||||||
asBarrier: true,
|
asBarrier: true,
|
||||||
constraints: BoxConstraints.loose(const Size(460, 460)),
|
constraints: BoxConstraints.loose(const Size(460, 460)),
|
||||||
|
@ -176,7 +176,7 @@ class _AddSortButtonState extends State<_AddSortButton> {
|
|||||||
mutex: widget.popoverMutex,
|
mutex: widget.popoverMutex,
|
||||||
direction: PopoverDirection.bottomWithLeftAligned,
|
direction: PopoverDirection.bottomWithLeftAligned,
|
||||||
constraints: BoxConstraints.loose(const Size(200, 300)),
|
constraints: BoxConstraints.loose(const Size(200, 300)),
|
||||||
offset: const Offset(0, 10),
|
offset: const Offset(0, 8),
|
||||||
triggerActions: PopoverTriggerFlags.none,
|
triggerActions: PopoverTriggerFlags.none,
|
||||||
asBarrier: true,
|
asBarrier: true,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
|
@ -30,20 +30,23 @@ class _FilterButtonState extends State<FilterButton> {
|
|||||||
|
|
||||||
return _wrapPopover(
|
return _wrapPopover(
|
||||||
context,
|
context,
|
||||||
FlowyTextButton(
|
SizedBox(
|
||||||
LocaleKeys.grid_settings_filter.tr(),
|
height: 26,
|
||||||
fontColor: textColor,
|
child: FlowyTextButton(
|
||||||
fillColor: Colors.transparent,
|
LocaleKeys.grid_settings_filter.tr(),
|
||||||
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
fontColor: textColor,
|
||||||
padding: GridSize.typeOptionContentInsets,
|
fillColor: Colors.transparent,
|
||||||
onPressed: () {
|
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
||||||
final bloc = context.read<GridFilterMenuBloc>();
|
padding: GridSize.typeOptionContentInsets,
|
||||||
if (bloc.state.filters.isEmpty) {
|
onPressed: () {
|
||||||
_popoverController.show();
|
final bloc = context.read<GridFilterMenuBloc>();
|
||||||
} else {
|
if (bloc.state.filters.isEmpty) {
|
||||||
bloc.add(const GridFilterMenuEvent.toggleMenu());
|
_popoverController.show();
|
||||||
}
|
} else {
|
||||||
},
|
bloc.add(const GridFilterMenuEvent.toggleMenu());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -55,7 +58,7 @@ class _FilterButtonState extends State<FilterButton> {
|
|||||||
controller: _popoverController,
|
controller: _popoverController,
|
||||||
direction: PopoverDirection.bottomWithLeftAligned,
|
direction: PopoverDirection.bottomWithLeftAligned,
|
||||||
constraints: BoxConstraints.loose(const Size(200, 300)),
|
constraints: BoxConstraints.loose(const Size(200, 300)),
|
||||||
offset: const Offset(0, 10),
|
offset: const Offset(0, 8),
|
||||||
triggerActions: PopoverTriggerFlags.none,
|
triggerActions: PopoverTriggerFlags.none,
|
||||||
child: child,
|
child: child,
|
||||||
popupBuilder: (BuildContext context) {
|
popupBuilder: (BuildContext context) {
|
||||||
|
@ -109,7 +109,7 @@ class _GridPropertyCellState extends State<_GridPropertyCell> {
|
|||||||
return AppFlowyPopover(
|
return AppFlowyPopover(
|
||||||
mutex: widget.popoverMutex,
|
mutex: widget.popoverMutex,
|
||||||
controller: _popoverController,
|
controller: _popoverController,
|
||||||
offset: const Offset(20, 0),
|
offset: const Offset(8, 0),
|
||||||
direction: PopoverDirection.leftWithTopAligned,
|
direction: PopoverDirection.leftWithTopAligned,
|
||||||
constraints: BoxConstraints.loose(const Size(240, 400)),
|
constraints: BoxConstraints.loose(const Size(240, 400)),
|
||||||
triggerActions: PopoverTriggerFlags.none,
|
triggerActions: PopoverTriggerFlags.none,
|
||||||
|
@ -41,23 +41,26 @@ class _SettingButtonState extends State<SettingButton> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
builder: (context, settingContext) {
|
builder: (context, settingContext) {
|
||||||
return AppFlowyPopover(
|
return SizedBox(
|
||||||
controller: _popoverController,
|
height: 26,
|
||||||
constraints: BoxConstraints.loose(const Size(260, 400)),
|
child: AppFlowyPopover(
|
||||||
direction: PopoverDirection.bottomWithLeftAligned,
|
controller: _popoverController,
|
||||||
offset: const Offset(0, 10),
|
constraints: BoxConstraints.loose(const Size(260, 400)),
|
||||||
margin: EdgeInsets.zero,
|
direction: PopoverDirection.bottomWithLeftAligned,
|
||||||
triggerActions: PopoverTriggerFlags.none,
|
offset: const Offset(0, 8),
|
||||||
child: FlowyTextButton(
|
margin: EdgeInsets.zero,
|
||||||
LocaleKeys.settings_title.tr(),
|
triggerActions: PopoverTriggerFlags.none,
|
||||||
fillColor: Colors.transparent,
|
child: FlowyTextButton(
|
||||||
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
LocaleKeys.settings_title.tr(),
|
||||||
padding: GridSize.typeOptionContentInsets,
|
fillColor: Colors.transparent,
|
||||||
onPressed: () => _popoverController.show(),
|
hoverColor: AFThemeExtension.of(context).lightGreyHover,
|
||||||
|
padding: GridSize.typeOptionContentInsets,
|
||||||
|
onPressed: () => _popoverController.show(),
|
||||||
|
),
|
||||||
|
popupBuilder: (BuildContext context) {
|
||||||
|
return _GridSettingListPopover(settingContext: settingContext);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
popupBuilder: (BuildContext context) {
|
|
||||||
return _GridSettingListPopover(settingContext: settingContext);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -58,7 +58,7 @@ class _SortButtonState extends State<SortButton> {
|
|||||||
controller: _popoverController,
|
controller: _popoverController,
|
||||||
direction: PopoverDirection.bottomWithLeftAligned,
|
direction: PopoverDirection.bottomWithLeftAligned,
|
||||||
constraints: BoxConstraints.loose(const Size(200, 300)),
|
constraints: BoxConstraints.loose(const Size(200, 300)),
|
||||||
offset: const Offset(0, 10),
|
offset: const Offset(0, 8),
|
||||||
margin: const EdgeInsets.all(6),
|
margin: const EdgeInsets.all(6),
|
||||||
triggerActions: PopoverTriggerFlags.none,
|
triggerActions: PopoverTriggerFlags.none,
|
||||||
child: child,
|
child: child,
|
||||||
|
@ -145,7 +145,7 @@ class _ChecklistOptionCellState extends State<_ChecklistOptionCell> {
|
|||||||
Widget _wrapPopover(Widget child) {
|
Widget _wrapPopover(Widget child) {
|
||||||
return AppFlowyPopover(
|
return AppFlowyPopover(
|
||||||
controller: _popoverController,
|
controller: _popoverController,
|
||||||
offset: const Offset(20, 0),
|
offset: const Offset(8, 0),
|
||||||
asBarrier: true,
|
asBarrier: true,
|
||||||
constraints: BoxConstraints.loose(const Size(200, 300)),
|
constraints: BoxConstraints.loose(const Size(200, 300)),
|
||||||
mutex: widget.popoverMutex,
|
mutex: widget.popoverMutex,
|
||||||
|
@ -376,7 +376,7 @@ class _DateTypeOptionButton extends StatelessWidget {
|
|||||||
return AppFlowyPopover(
|
return AppFlowyPopover(
|
||||||
mutex: popoverMutex,
|
mutex: popoverMutex,
|
||||||
triggerActions: PopoverTriggerFlags.hover | PopoverTriggerFlags.click,
|
triggerActions: PopoverTriggerFlags.hover | PopoverTriggerFlags.click,
|
||||||
offset: const Offset(20, 0),
|
offset: const Offset(8, 0),
|
||||||
margin: EdgeInsets.zero,
|
margin: EdgeInsets.zero,
|
||||||
constraints: BoxConstraints.loose(const Size(140, 100)),
|
constraints: BoxConstraints.loose(const Size(140, 100)),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@ -431,7 +431,7 @@ class _CalDateTimeSettingState extends State<_CalDateTimeSetting> {
|
|||||||
AppFlowyPopover(
|
AppFlowyPopover(
|
||||||
mutex: timeSettingPopoverMutex,
|
mutex: timeSettingPopoverMutex,
|
||||||
triggerActions: PopoverTriggerFlags.hover | PopoverTriggerFlags.click,
|
triggerActions: PopoverTriggerFlags.hover | PopoverTriggerFlags.click,
|
||||||
offset: const Offset(20, 0),
|
offset: const Offset(8, 0),
|
||||||
popupBuilder: (BuildContext context) {
|
popupBuilder: (BuildContext context) {
|
||||||
return DateFormatList(
|
return DateFormatList(
|
||||||
selectedFormat: widget.dateTypeOptionPB.dateFormat,
|
selectedFormat: widget.dateTypeOptionPB.dateFormat,
|
||||||
@ -449,7 +449,7 @@ class _CalDateTimeSettingState extends State<_CalDateTimeSetting> {
|
|||||||
AppFlowyPopover(
|
AppFlowyPopover(
|
||||||
mutex: timeSettingPopoverMutex,
|
mutex: timeSettingPopoverMutex,
|
||||||
triggerActions: PopoverTriggerFlags.hover | PopoverTriggerFlags.click,
|
triggerActions: PopoverTriggerFlags.hover | PopoverTriggerFlags.click,
|
||||||
offset: const Offset(20, 0),
|
offset: const Offset(8, 0),
|
||||||
popupBuilder: (BuildContext context) {
|
popupBuilder: (BuildContext context) {
|
||||||
return TimeFormatList(
|
return TimeFormatList(
|
||||||
selectedFormat: widget.dateTypeOptionPB.timeFormat,
|
selectedFormat: widget.dateTypeOptionPB.timeFormat,
|
||||||
|
@ -285,7 +285,7 @@ class _SelectOptionCellState extends State<_SelectOptionCell> {
|
|||||||
);
|
);
|
||||||
return AppFlowyPopover(
|
return AppFlowyPopover(
|
||||||
controller: _popoverController,
|
controller: _popoverController,
|
||||||
offset: const Offset(20, 0),
|
offset: const Offset(8, 0),
|
||||||
margin: EdgeInsets.zero,
|
margin: EdgeInsets.zero,
|
||||||
asBarrier: true,
|
asBarrier: true,
|
||||||
constraints: BoxConstraints.loose(const Size(200, 460)),
|
constraints: BoxConstraints.loose(const Size(200, 460)),
|
||||||
|
@ -127,7 +127,7 @@ class _GridURLCellState extends GridCellState<GridURLCell> {
|
|||||||
constraints: BoxConstraints.loose(const Size(300, 160)),
|
constraints: BoxConstraints.loose(const Size(300, 160)),
|
||||||
direction: PopoverDirection.bottomWithLeftAligned,
|
direction: PopoverDirection.bottomWithLeftAligned,
|
||||||
triggerActions: PopoverTriggerFlags.none,
|
triggerActions: PopoverTriggerFlags.none,
|
||||||
offset: const Offset(0, 20),
|
offset: const Offset(0, 8),
|
||||||
child: SizedBox.expand(
|
child: SizedBox.expand(
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
child: Align(alignment: Alignment.centerLeft, child: richText),
|
child: Align(alignment: Alignment.centerLeft, child: richText),
|
||||||
@ -210,7 +210,7 @@ class _EditURLAccessoryState extends State<_EditURLAccessory>
|
|||||||
constraints: BoxConstraints.loose(const Size(300, 160)),
|
constraints: BoxConstraints.loose(const Size(300, 160)),
|
||||||
controller: _popoverController,
|
controller: _popoverController,
|
||||||
direction: PopoverDirection.bottomWithLeftAligned,
|
direction: PopoverDirection.bottomWithLeftAligned,
|
||||||
offset: const Offset(0, 20),
|
offset: const Offset(0, 8),
|
||||||
child: svgWidget(
|
child: svgWidget(
|
||||||
"editor/edit",
|
"editor/edit",
|
||||||
color: Theme.of(context).colorScheme.onSurface,
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
|
@ -12,13 +12,15 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as p;
|
||||||
import 'change_cover_popover.dart';
|
import 'change_cover_popover.dart';
|
||||||
|
|
||||||
part 'cover_image_picker_bloc.freezed.dart';
|
part 'cover_image_picker_bloc.freezed.dart';
|
||||||
|
|
||||||
class CoverImagePickerBloc
|
class CoverImagePickerBloc
|
||||||
extends Bloc<CoverImagePickerEvent, CoverImagePickerState> {
|
extends Bloc<CoverImagePickerEvent, CoverImagePickerState> {
|
||||||
|
static const allowedExtensions = ['jpg', 'png', 'jpeg'];
|
||||||
|
|
||||||
CoverImagePickerBloc() : super(const CoverImagePickerState.initial()) {
|
CoverImagePickerBloc() : super(const CoverImagePickerState.initial()) {
|
||||||
on<CoverImagePickerEvent>(
|
on<CoverImagePickerEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
@ -28,7 +30,7 @@ class CoverImagePickerBloc
|
|||||||
},
|
},
|
||||||
urlSubmit: (UrlSubmit urlSubmit) async {
|
urlSubmit: (UrlSubmit urlSubmit) async {
|
||||||
emit(const CoverImagePickerState.loading());
|
emit(const CoverImagePickerState.loading());
|
||||||
final validateImage = await _validateUrl(urlSubmit.path);
|
final validateImage = await _validateURL(urlSubmit.path);
|
||||||
if (validateImage) {
|
if (validateImage) {
|
||||||
emit(CoverImagePickerState.networkImage(left(urlSubmit.path)));
|
emit(CoverImagePickerState.networkImage(left(urlSubmit.path)));
|
||||||
} else {
|
} else {
|
||||||
@ -86,28 +88,22 @@ class CoverImagePickerBloc
|
|||||||
if (state is FileImagePicked) {
|
if (state is FileImagePicked) {
|
||||||
try {
|
try {
|
||||||
final path = state.path;
|
final path = state.path;
|
||||||
final newPath = '$directory/${path.split("\\").last}';
|
final newPath = p.join(directory, p.split(path).last);
|
||||||
final newFile = await File(path).copy(newPath);
|
final newFile = await File(path).copy(newPath);
|
||||||
imagePaths.add(newFile.path);
|
imagePaths.add(newFile.path);
|
||||||
await prefs.setStringList(kLocalImagesKey, imagePaths);
|
|
||||||
return imagePaths;
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} else if (state is NetworkImagePicked) {
|
} else if (state is NetworkImagePicked) {
|
||||||
try {
|
try {
|
||||||
String? url = state.successOrFail.fold((path) => path, (r) => null);
|
final url = state.successOrFail.fold((path) => path, (r) => null);
|
||||||
if (url != null) {
|
if (url != null) {
|
||||||
final response = await http.get(Uri.parse(url));
|
final response = await http.get(Uri.parse(url));
|
||||||
final newPath =
|
final newPath = p.join(directory, _networkImageName(url));
|
||||||
"$directory/IMG_$_timeStampString.${_getExtention(url)}";
|
|
||||||
|
|
||||||
final imageFile = File(newPath);
|
final imageFile = File(newPath);
|
||||||
await imageFile.create();
|
await imageFile.create();
|
||||||
await imageFile.writeAsBytes(response.bodyBytes);
|
await imageFile.writeAsBytes(response.bodyBytes);
|
||||||
imagePaths.add(imageFile.absolute.path);
|
imagePaths.add(imageFile.absolute.path);
|
||||||
await prefs.setStringList(kLocalImagesKey, imagePaths);
|
|
||||||
return imagePaths;
|
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -115,59 +111,71 @@ class CoverImagePickerBloc
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
await prefs.setStringList(kLocalImagesKey, imagePaths);
|
||||||
|
return imagePaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
_pickImages() async {
|
Future<String?> _pickImages() async {
|
||||||
FilePickerResult? result = await getIt<FilePickerService>().pickFiles(
|
final result = await getIt<FilePickerService>().pickFiles(
|
||||||
dialogTitle: LocaleKeys.document_plugins_cover_addLocalImage.tr(),
|
dialogTitle: LocaleKeys.document_plugins_cover_addLocalImage.tr(),
|
||||||
allowMultiple: false,
|
allowMultiple: false,
|
||||||
type: fp.FileType.image,
|
type: fp.FileType.image,
|
||||||
allowedExtensions: ['jpg', 'png', 'jpeg'],
|
allowedExtensions: allowedExtensions,
|
||||||
);
|
);
|
||||||
if (result != null && result.files.isNotEmpty) {
|
if (result != null && result.files.isNotEmpty) {
|
||||||
final path = result.files.first.path;
|
return result.files.first.path;
|
||||||
if (path != null) {
|
|
||||||
return path;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> _coverPath() async {
|
Future<String> _coverPath() async {
|
||||||
final directory = await getIt<SettingsLocationCubit>().fetchLocation();
|
final directory = await getIt<SettingsLocationCubit>().fetchLocation();
|
||||||
return Directory(path.join(directory, 'covers'))
|
return Directory(p.join(directory, 'covers'))
|
||||||
.create(recursive: true)
|
.create(recursive: true)
|
||||||
.then((value) => value.path);
|
.then((value) => value.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
String get _timeStampString =>
|
String _networkImageName(String url) {
|
||||||
DateTime.now().millisecondsSinceEpoch.toString();
|
return 'IMG_${DateTime.now().millisecondsSinceEpoch.toString()}.${_getExtention(
|
||||||
|
url,
|
||||||
|
fromNetwork: true,
|
||||||
|
)}';
|
||||||
|
}
|
||||||
|
|
||||||
String? _getExtention(String path) => path.contains(".jpg")
|
String? _getExtention(
|
||||||
? "jpg"
|
String path, {
|
||||||
: path.contains(".png")
|
bool fromNetwork = false,
|
||||||
? "png"
|
}) {
|
||||||
: path.contains(".jpeg")
|
String? ext;
|
||||||
? "jpeg"
|
if (!fromNetwork) {
|
||||||
: (path.contains("auto=format") && path.contains("unsplash"))
|
final extension = p.extension(path);
|
||||||
? "jpeg"
|
if (extension.isEmpty) {
|
||||||
: null;
|
return null;
|
||||||
|
|
||||||
_validateUrl(String path) async {
|
|
||||||
if (_getExtention(path) != null) {
|
|
||||||
try {
|
|
||||||
final response = await http.get(Uri.parse(path));
|
|
||||||
if (response.statusCode == 200) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
ext = extension.substring(1);
|
||||||
} else {
|
} else {
|
||||||
|
final uri = Uri.parse(path);
|
||||||
|
final paramters = uri.queryParameters;
|
||||||
|
final dl = paramters['dl'];
|
||||||
|
if (dl != null) {
|
||||||
|
ext = p.extension(dl).substring(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allowedExtensions.contains(ext)) {
|
||||||
|
return ext;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> _validateURL(String path) async {
|
||||||
|
final extension = _getExtention(path, fromNetwork: true);
|
||||||
|
if (extension == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
final response = await http.head(Uri.parse(path));
|
||||||
|
return response.statusCode == 200;
|
||||||
|
} catch (e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,7 @@ class ShareActionList extends StatelessWidget {
|
|||||||
final docShareBloc = context.read<DocShareBloc>();
|
final docShareBloc = context.read<DocShareBloc>();
|
||||||
return PopoverActionList<ShareActionWrapper>(
|
return PopoverActionList<ShareActionWrapper>(
|
||||||
direction: PopoverDirection.bottomWithCenterAligned,
|
direction: PopoverDirection.bottomWithCenterAligned,
|
||||||
|
offset: const Offset(0, 8),
|
||||||
actions: ShareAction.values
|
actions: ShareAction.values
|
||||||
.map((action) => ShareActionWrapper(action))
|
.map((action) => ShareActionWrapper(action))
|
||||||
.toList(),
|
.toList(),
|
||||||
|
@ -83,11 +83,10 @@ class UserWorkspaceListener {
|
|||||||
PublishNotifier();
|
PublishNotifier();
|
||||||
|
|
||||||
FolderNotificationListener? _listener;
|
FolderNotificationListener? _listener;
|
||||||
final UserProfilePB _userProfile;
|
|
||||||
|
|
||||||
UserWorkspaceListener({
|
UserWorkspaceListener({
|
||||||
required UserProfilePB userProfile,
|
required UserProfilePB userProfile,
|
||||||
}) : _userProfile = userProfile;
|
});
|
||||||
|
|
||||||
void start({
|
void start({
|
||||||
void Function(AuthNotifyValue)? onAuthChanged,
|
void Function(AuthNotifyValue)? onAuthChanged,
|
||||||
@ -106,14 +105,18 @@ class UserWorkspaceListener {
|
|||||||
_settingChangedNotifier?.addPublishListener(onSettingUpdated);
|
_settingChangedNotifier?.addPublishListener(onSettingUpdated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The "current-workspace" is predefined in the backend. Do not try to
|
||||||
|
// modify it
|
||||||
_listener = FolderNotificationListener(
|
_listener = FolderNotificationListener(
|
||||||
objectId: _userProfile.token,
|
objectId: "current-workspace",
|
||||||
handler: _handleObservableType,
|
handler: _handleObservableType,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleObservableType(
|
void _handleObservableType(
|
||||||
FolderNotification ty, Either<Uint8List, FlowyError> result) {
|
FolderNotification ty,
|
||||||
|
Either<Uint8List, FlowyError> result,
|
||||||
|
) {
|
||||||
switch (ty) {
|
switch (ty) {
|
||||||
case FolderNotification.DidCreateWorkspace:
|
case FolderNotification.DidCreateWorkspace:
|
||||||
case FolderNotification.DidDeleteWorkspace:
|
case FolderNotification.DidDeleteWorkspace:
|
||||||
|
@ -48,6 +48,7 @@ class AddButton extends StatelessWidget {
|
|||||||
return PopoverActionList<PopoverAction>(
|
return PopoverActionList<PopoverAction>(
|
||||||
direction: PopoverDirection.bottomWithLeftAligned,
|
direction: PopoverDirection.bottomWithLeftAligned,
|
||||||
actions: actions,
|
actions: actions,
|
||||||
|
offset: const Offset(0, 8),
|
||||||
buildChild: (controller) {
|
buildChild: (controller) {
|
||||||
return FlowyIconButton(
|
return FlowyIconButton(
|
||||||
width: 22,
|
width: 22,
|
||||||
|
@ -42,6 +42,7 @@ class BubbleActionList extends StatelessWidget {
|
|||||||
return PopoverActionList<PopoverAction>(
|
return PopoverActionList<PopoverAction>(
|
||||||
direction: PopoverDirection.topWithRightAligned,
|
direction: PopoverDirection.topWithRightAligned,
|
||||||
actions: actions,
|
actions: actions,
|
||||||
|
offset: const Offset(0, -8),
|
||||||
buildChild: (controller) {
|
buildChild: (controller) {
|
||||||
return FlowyTextButton(
|
return FlowyTextButton(
|
||||||
'?',
|
'?',
|
||||||
|
@ -13,6 +13,7 @@ class PopoverActionList<T extends PopoverAction> extends StatefulWidget {
|
|||||||
final Widget Function(PopoverController) buildChild;
|
final Widget Function(PopoverController) buildChild;
|
||||||
final VoidCallback? onClosed;
|
final VoidCallback? onClosed;
|
||||||
final bool asBarrier;
|
final bool asBarrier;
|
||||||
|
final Offset offset;
|
||||||
|
|
||||||
const PopoverActionList({
|
const PopoverActionList({
|
||||||
required this.actions,
|
required this.actions,
|
||||||
@ -22,6 +23,7 @@ class PopoverActionList<T extends PopoverAction> extends StatefulWidget {
|
|||||||
this.onClosed,
|
this.onClosed,
|
||||||
this.direction = PopoverDirection.rightWithTopAligned,
|
this.direction = PopoverDirection.rightWithTopAligned,
|
||||||
this.asBarrier = false,
|
this.asBarrier = false,
|
||||||
|
this.offset = Offset.zero,
|
||||||
this.constraints = const BoxConstraints(
|
this.constraints = const BoxConstraints(
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
maxWidth: 460,
|
maxWidth: 460,
|
||||||
@ -54,6 +56,7 @@ class _PopoverActionListState<T extends PopoverAction>
|
|||||||
constraints: widget.constraints,
|
constraints: widget.constraints,
|
||||||
direction: widget.direction,
|
direction: widget.direction,
|
||||||
mutex: widget.mutex,
|
mutex: widget.mutex,
|
||||||
|
offset: widget.offset,
|
||||||
triggerActions: PopoverTriggerFlags.none,
|
triggerActions: PopoverTriggerFlags.none,
|
||||||
onClose: widget.onClosed,
|
onClose: widget.onClosed,
|
||||||
popupBuilder: (BuildContext popoverContext) {
|
popupBuilder: (BuildContext popoverContext) {
|
||||||
|
@ -69,6 +69,37 @@ async function moveKanbanBoardRow() {
|
|||||||
// Create row in no status group
|
// Create row in no status group
|
||||||
const firstGroup = databaseController.groups.getValue()[1];
|
const firstGroup = databaseController.groups.getValue()[1];
|
||||||
const secondGroup = databaseController.groups.getValue()[2];
|
const secondGroup = databaseController.groups.getValue()[2];
|
||||||
|
// subscribe the group changes
|
||||||
|
firstGroup.subscribe({
|
||||||
|
onRemoveRow: (groupId, deleteRowId) => {
|
||||||
|
console.log(groupId + 'did remove:' + deleteRowId);
|
||||||
|
},
|
||||||
|
onInsertRow: (groupId, rowPB) => {
|
||||||
|
console.log(groupId + 'did insert:' + rowPB.id);
|
||||||
|
},
|
||||||
|
onUpdateRow: (groupId, rowPB) => {
|
||||||
|
console.log(groupId + 'did update:' + rowPB.id);
|
||||||
|
},
|
||||||
|
onCreateRow: (groupId, rowPB) => {
|
||||||
|
console.log(groupId + 'did create:' + rowPB.id);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
secondGroup.subscribe({
|
||||||
|
onRemoveRow: (groupId, deleteRowId) => {
|
||||||
|
console.log(groupId + 'did remove:' + deleteRowId);
|
||||||
|
},
|
||||||
|
onInsertRow: (groupId, rowPB) => {
|
||||||
|
console.log(groupId + 'did insert:' + rowPB.id);
|
||||||
|
},
|
||||||
|
onUpdateRow: (groupId, rowPB) => {
|
||||||
|
console.log(groupId + 'did update:' + rowPB.id);
|
||||||
|
},
|
||||||
|
onCreateRow: (groupId, rowPB) => {
|
||||||
|
console.log(groupId + 'did create:' + rowPB.id);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const row = firstGroup.rowAtIndex(0).unwrap();
|
const row = firstGroup.rowAtIndex(0).unwrap();
|
||||||
await databaseController.moveRow(row.id, secondGroup.groupId);
|
await databaseController.moveRow(row.id, secondGroup.groupId);
|
||||||
|
|
||||||
|
@ -61,12 +61,19 @@ export class DatabaseBackendService {
|
|||||||
return DatabaseEventCreateRow(payload);
|
return DatabaseEventCreateRow(payload);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Move a row to another group
|
/// Move the row from one group to another group
|
||||||
moveRow = (rowId: string, groupId?: string) => {
|
/// [groupId] can be the moving row's group id or others.
|
||||||
const payload = MoveGroupRowPayloadPB.fromObject({ view_id: this.viewId, from_row_id: rowId });
|
/// [toRowId] is used to locate the moving row location.
|
||||||
if (groupId !== undefined) {
|
moveGroupRow = (fromRowId: string, groupId: string, toRowId?: string) => {
|
||||||
payload.to_group_id = groupId;
|
const payload = MoveGroupRowPayloadPB.fromObject({
|
||||||
|
view_id: this.viewId,
|
||||||
|
from_row_id: fromRowId,
|
||||||
|
to_group_id: groupId,
|
||||||
|
});
|
||||||
|
if (toRowId !== undefined) {
|
||||||
|
payload.to_row_id = toRowId;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DatabaseEventMoveGroupRow(payload);
|
return DatabaseEventMoveGroupRow(payload);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -106,6 +113,7 @@ export class DatabaseBackendService {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Get all groups in database
|
/// Get all groups in database
|
||||||
|
/// It should only call once after the board open
|
||||||
loadGroups = () => {
|
loadGroups = () => {
|
||||||
const payload = DatabaseViewIdPB.fromObject({ value: this.viewId });
|
const payload = DatabaseViewIdPB.fromObject({ value: this.viewId });
|
||||||
return DatabaseEventGetGroups(payload);
|
return DatabaseEventGetGroups(payload);
|
||||||
|
@ -76,7 +76,7 @@ export class DatabaseController {
|
|||||||
};
|
};
|
||||||
|
|
||||||
moveRow = (rowId: string, groupId: string) => {
|
moveRow = (rowId: string, groupId: string) => {
|
||||||
return this.backendService.moveRow(rowId, groupId);
|
return this.backendService.moveGroupRow(rowId, groupId);
|
||||||
};
|
};
|
||||||
|
|
||||||
exchangeRow = async (fromRowId: string, toRowId: string) => {
|
exchangeRow = async (fromRowId: string, toRowId: string) => {
|
||||||
|
@ -115,6 +115,8 @@ pub fn move_group_row(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update the corresponding row's cell content.
|
// Update the corresponding row's cell content.
|
||||||
|
// If the from_index is none which means the row is not belong to this group before and
|
||||||
|
// it is moved from other groups.
|
||||||
if from_index.is_none() {
|
if from_index.is_none() {
|
||||||
let cell_rev = make_inserted_cell_rev(&group.id, field_rev);
|
let cell_rev = make_inserted_cell_rev(&group.id, field_rev);
|
||||||
if let Some(cell_rev) = cell_rev {
|
if let Some(cell_rev) = cell_rev {
|
||||||
@ -126,7 +128,6 @@ pub fn move_group_row(
|
|||||||
row_changeset
|
row_changeset
|
||||||
.cell_by_field_id
|
.cell_by_field_id
|
||||||
.insert(field_rev.id.clone(), cell_rev);
|
.insert(field_rev.id.clone(), cell_rev);
|
||||||
changeset.updated_rows.push(RowPB::from(*row_rev));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use flowy_sqlite::kv::KV;
|
use flowy_sqlite::kv::KV;
|
||||||
use folder_model::{AppRevision, WorkspaceRevision};
|
use folder_model::{AppRevision, WorkspaceRevision};
|
||||||
|
use lib_dispatch::prelude::ToBytes;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub struct WorkspaceController {
|
pub struct WorkspaceController {
|
||||||
@ -41,7 +42,6 @@ impl WorkspaceController {
|
|||||||
) -> Result<WorkspaceRevision, FlowyError> {
|
) -> Result<WorkspaceRevision, FlowyError> {
|
||||||
let workspace = self.create_workspace_on_server(params.clone()).await?;
|
let workspace = self.create_workspace_on_server(params.clone()).await?;
|
||||||
let user_id = self.user.user_id()?;
|
let user_id = self.user.user_id()?;
|
||||||
let token = self.user.token()?;
|
|
||||||
let workspaces = self
|
let workspaces = self
|
||||||
.persistence
|
.persistence
|
||||||
.begin_transaction(|transaction| {
|
.begin_transaction(|transaction| {
|
||||||
@ -53,9 +53,7 @@ impl WorkspaceController {
|
|||||||
.map(|workspace_rev| workspace_rev.into())
|
.map(|workspace_rev| workspace_rev.into())
|
||||||
.collect();
|
.collect();
|
||||||
let repeated_workspace = RepeatedWorkspacePB { items: workspaces };
|
let repeated_workspace = RepeatedWorkspacePB { items: workspaces };
|
||||||
send_notification(&token, FolderNotification::DidCreateWorkspace)
|
send_workspace_notification(FolderNotification::DidCreateWorkspace, repeated_workspace);
|
||||||
.payload(repeated_workspace)
|
|
||||||
.send();
|
|
||||||
set_current_workspace(&user_id, &workspace.id);
|
set_current_workspace(&user_id, &workspace.id);
|
||||||
Ok(workspace)
|
Ok(workspace)
|
||||||
}
|
}
|
||||||
@ -76,9 +74,7 @@ impl WorkspaceController {
|
|||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
send_notification(&workspace_id, FolderNotification::DidUpdateWorkspace)
|
send_workspace_notification(FolderNotification::DidUpdateWorkspace, workspace);
|
||||||
.payload(workspace)
|
|
||||||
.send();
|
|
||||||
self.update_workspace_on_server(params)?;
|
self.update_workspace_on_server(params)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -87,7 +83,6 @@ impl WorkspaceController {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) async fn delete_workspace(&self, workspace_id: &str) -> Result<(), FlowyError> {
|
pub(crate) async fn delete_workspace(&self, workspace_id: &str) -> Result<(), FlowyError> {
|
||||||
let user_id = self.user.user_id()?;
|
let user_id = self.user.user_id()?;
|
||||||
let token = self.user.token()?;
|
|
||||||
let repeated_workspace = self
|
let repeated_workspace = self
|
||||||
.persistence
|
.persistence
|
||||||
.begin_transaction(|transaction| {
|
.begin_transaction(|transaction| {
|
||||||
@ -95,9 +90,8 @@ impl WorkspaceController {
|
|||||||
self.read_workspaces(None, &user_id, &transaction)
|
self.read_workspaces(None, &user_id, &transaction)
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
send_notification(&token, FolderNotification::DidDeleteWorkspace)
|
|
||||||
.payload(repeated_workspace)
|
send_workspace_notification(FolderNotification::DidDeleteWorkspace, repeated_workspace);
|
||||||
.send();
|
|
||||||
self.delete_workspace_on_server(workspace_id)?;
|
self.delete_workspace_on_server(workspace_id)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -224,7 +218,6 @@ pub async fn notify_workspace_setting_did_change(
|
|||||||
view_id: &str,
|
view_id: &str,
|
||||||
) -> FlowyResult<()> {
|
) -> FlowyResult<()> {
|
||||||
let user_id = folder_manager.user.user_id()?;
|
let user_id = folder_manager.user.user_id()?;
|
||||||
let token = folder_manager.user.token()?;
|
|
||||||
let workspace_id = get_current_workspace(&user_id)?;
|
let workspace_id = get_current_workspace(&user_id)?;
|
||||||
|
|
||||||
let workspace_setting = folder_manager
|
let workspace_setting = folder_manager
|
||||||
@ -250,13 +243,22 @@ pub async fn notify_workspace_setting_did_change(
|
|||||||
Ok(setting)
|
Ok(setting)
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
send_workspace_notification(
|
||||||
send_notification(&token, FolderNotification::DidUpdateWorkspaceSetting)
|
FolderNotification::DidUpdateWorkspaceSetting,
|
||||||
.payload(workspace_setting)
|
workspace_setting,
|
||||||
.send();
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The [CURRENT_WORKSPACE] represents as the current workspace that opened by the
|
||||||
|
/// user. Only one workspace can be opened at a time.
|
||||||
|
const CURRENT_WORKSPACE: &str = "current-workspace";
|
||||||
|
fn send_workspace_notification<T: ToBytes>(ty: FolderNotification, payload: T) {
|
||||||
|
send_notification(CURRENT_WORKSPACE, ty)
|
||||||
|
.payload(payload)
|
||||||
|
.send();
|
||||||
|
}
|
||||||
|
|
||||||
const CURRENT_WORKSPACE_ID: &str = "current_workspace_id";
|
const CURRENT_WORKSPACE_ID: &str = "current_workspace_id";
|
||||||
|
|
||||||
pub fn set_current_workspace(_user_id: &str, workspace_id: &str) {
|
pub fn set_current_workspace(_user_id: &str, workspace_id: &str) {
|
||||||
|
@ -6,39 +6,56 @@ RED="\e[31m"
|
|||||||
ENDCOLOR="\e[0m"
|
ENDCOLOR="\e[0m"
|
||||||
|
|
||||||
printMessage() {
|
printMessage() {
|
||||||
printf "${YELLOW}AppFlowy : $1${ENDCOLOR}\n"
|
printf "${YELLOW}AppFlowy : $1${ENDCOLOR}\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
printSuccess() {
|
printSuccess() {
|
||||||
printf "${GREEN}AppFlowy : $1${ENDCOLOR}\n"
|
printf "${GREEN}AppFlowy : $1${ENDCOLOR}\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
printError() {
|
printError() {
|
||||||
printf "${RED}AppFlowy : $1${ENDCOLOR}\n"
|
printf "${RED}AppFlowy : $1${ENDCOLOR}\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Note: This script does not install applications which are installed by the package manager. There are too many package managers out there.
|
# Note: This script does not install applications which are installed by the package manager. There are too many package managers out there.
|
||||||
|
|
||||||
# Install Rust
|
# Install Rust
|
||||||
printMessage "The Rust programming language is required to compile AppFlowy."
|
printMessage "The Rust programming language is required to compile AppFlowy."
|
||||||
printMessage "We can install it now if you don't already have it on your system."
|
printMessage "We can install it now if you don't already have it on your system."
|
||||||
|
|
||||||
read -p "$(printSuccess "Do you want to install Rust? [y/N]") " installrust
|
read -p "$(printSuccess "Do you want to install Rust? [y/N]") " installrust
|
||||||
|
|
||||||
if [ ${installrust^^} == "Y" ]; then
|
if [ ${installrust^^} == "Y" ]; then
|
||||||
printMessage "Installing Rust."
|
printMessage "Installing Rust."
|
||||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||||
source $HOME/.cargo/env
|
source $HOME/.cargo/env
|
||||||
rustup toolchain install stable
|
rustup toolchain install stable
|
||||||
rustup default stable
|
rustup default stable
|
||||||
else
|
else
|
||||||
printMessage "Skipping Rust installation."
|
printMessage "Skipping Rust installation."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Enable the flutter stable channel
|
|
||||||
printMessage "Setting up Flutter"
|
printMessage "Setting up Flutter"
|
||||||
flutter channel stable
|
# Get the current Flutter version
|
||||||
|
FLUTTER_VERSION=$(flutter --version | grep -oP 'Flutter \K\S+')
|
||||||
|
# Check if the current version is 3.3.10
|
||||||
|
if [ "$FLUTTER_VERSION" = "3.3.10" ]; then
|
||||||
|
echo "Flutter version is already 3.3.10"
|
||||||
|
else
|
||||||
|
# Get the path to the Flutter SDK
|
||||||
|
FLUTTER_PATH=$(which flutter)
|
||||||
|
FLUTTER_PATH=${FLUTTER_PATH%/bin/flutter}
|
||||||
|
|
||||||
|
current_dir=$(pwd)
|
||||||
|
|
||||||
|
cd $FLUTTER_PATH
|
||||||
|
# Use git to checkout version 3.3.10 of Flutter
|
||||||
|
git checkout 3.3.10
|
||||||
|
# Get back to current working directory
|
||||||
|
cd "$current_dir"
|
||||||
|
|
||||||
|
echo "Switched to Flutter version 3.3.10"
|
||||||
|
fi
|
||||||
|
|
||||||
# Enable linux desktop
|
# Enable linux desktop
|
||||||
flutter config --enable-linux-desktop
|
flutter config --enable-linux-desktop
|
||||||
@ -47,9 +64,9 @@ flutter config --enable-linux-desktop
|
|||||||
flutter doctor
|
flutter doctor
|
||||||
|
|
||||||
printMessage "Installing keybinder-3.0"
|
printMessage "Installing keybinder-3.0"
|
||||||
if command apt-get &> /dev/null; then
|
if command apt-get &>/dev/null; then
|
||||||
sudo apt-get install keybinder-3.0-dev
|
sudo apt-get install keybinder-3.0-dev
|
||||||
elif command dnf &> /dev/null; then
|
elif command dnf &>/dev/null; then
|
||||||
sudo dnf install keybinder3-devel
|
sudo dnf install keybinder3-devel
|
||||||
else
|
else
|
||||||
echo 'Your system is not supported, please install keybinder3 manually.'
|
echo 'Your system is not supported, please install keybinder3 manually.'
|
||||||
@ -59,11 +76,11 @@ fi
|
|||||||
printMessage "Setting up githooks."
|
printMessage "Setting up githooks."
|
||||||
git config core.hooksPath .githooks
|
git config core.hooksPath .githooks
|
||||||
|
|
||||||
# Install go-gitlint
|
# Install go-gitlint
|
||||||
printMessage "Installing go-gitlint."
|
printMessage "Installing go-gitlint."
|
||||||
GOLINT_FILENAME="go-gitlint_1.1.0_linux_x86_64.tar.gz"
|
GOLINT_FILENAME="go-gitlint_1.1.0_linux_x86_64.tar.gz"
|
||||||
wget https://github.com/llorllale/go-gitlint/releases/download/1.1.0/${GOLINT_FILENAME}
|
wget https://github.com/llorllale/go-gitlint/releases/download/1.1.0/${GOLINT_FILENAME}
|
||||||
tar -zxv --directory .githooks/. -f ${GOLINT_FILENAME} gitlint
|
tar -zxv --directory .githooks/. -f ${GOLINT_FILENAME} gitlint
|
||||||
rm ${GOLINT_FILENAME}
|
rm ${GOLINT_FILENAME}
|
||||||
|
|
||||||
# Change to the frontend directory
|
# Change to the frontend directory
|
||||||
|
@ -17,8 +17,7 @@ printError() {
|
|||||||
printf "${RED}AppFlowy : $1${ENDCOLOR}\n"
|
printf "${RED}AppFlowy : $1${ENDCOLOR}\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Install Rust
|
||||||
# Install Rust
|
|
||||||
printMessage "The Rust programming language is required to compile AppFlowy."
|
printMessage "The Rust programming language is required to compile AppFlowy."
|
||||||
printMessage "We can install it now if you don't already have it on your system."
|
printMessage "We can install it now if you don't already have it on your system."
|
||||||
|
|
||||||
@ -28,7 +27,7 @@ if [[ "${installrust:-N}" == [Yy] ]]; then
|
|||||||
printMessage "Installing Rust."
|
printMessage "Installing Rust."
|
||||||
brew install rustup-init
|
brew install rustup-init
|
||||||
rustup-init -y --default-toolchain=stable
|
rustup-init -y --default-toolchain=stable
|
||||||
|
|
||||||
source "$HOME/.cargo/env"
|
source "$HOME/.cargo/env"
|
||||||
else
|
else
|
||||||
printMessage "Skipping Rust installation."
|
printMessage "Skipping Rust installation."
|
||||||
@ -36,11 +35,30 @@ fi
|
|||||||
|
|
||||||
# Install sqllite
|
# Install sqllite
|
||||||
printMessage "Installing sqlLite3."
|
printMessage "Installing sqlLite3."
|
||||||
brew install sqlite3
|
brew install sqlite3
|
||||||
|
|
||||||
# Enable the flutter stable channel
|
|
||||||
printMessage "Setting up Flutter"
|
printMessage "Setting up Flutter"
|
||||||
flutter channel stable
|
|
||||||
|
# Get the current Flutter version
|
||||||
|
FLUTTER_VERSION=$(flutter --version | grep -oE 'Flutter [^ ]+' | grep -oE '[^ ]+$')
|
||||||
|
# Check if the current version is 3.3.10
|
||||||
|
if [ "$FLUTTER_VERSION" = "3.3.10" ]; then
|
||||||
|
echo "Flutter version is already 3.3.10"
|
||||||
|
else
|
||||||
|
# Get the path to the Flutter SDK
|
||||||
|
FLUTTER_PATH=$(which flutter)
|
||||||
|
FLUTTER_PATH=${FLUTTER_PATH%/bin/flutter}
|
||||||
|
|
||||||
|
current_dir=$(pwd)
|
||||||
|
|
||||||
|
cd $FLUTTER_PATH
|
||||||
|
# Use git to checkout version 3.3.10 of Flutter
|
||||||
|
git checkout 3.3.10
|
||||||
|
# Get back to current working directory
|
||||||
|
cd "$current_dir"
|
||||||
|
|
||||||
|
echo "Switched to Flutter version 3.3.10"
|
||||||
|
fi
|
||||||
|
|
||||||
# Enable linux desktop
|
# Enable linux desktop
|
||||||
flutter config --enable-macos-desktop
|
flutter config --enable-macos-desktop
|
||||||
@ -52,11 +70,11 @@ flutter doctor
|
|||||||
printMessage "Setting up githooks."
|
printMessage "Setting up githooks."
|
||||||
git config core.hooksPath .githooks
|
git config core.hooksPath .githooks
|
||||||
|
|
||||||
# Install go-gitlint
|
# Install go-gitlint
|
||||||
printMessage "Installing go-gitlint."
|
printMessage "Installing go-gitlint."
|
||||||
GOLINT_FILENAME="go-gitlint_1.1.0_osx_x86_64.tar.gz"
|
GOLINT_FILENAME="go-gitlint_1.1.0_osx_x86_64.tar.gz"
|
||||||
curl -L https://github.com/llorllale/go-gitlint/releases/download/1.1.0/${GOLINT_FILENAME} --output ${GOLINT_FILENAME}
|
curl -L https://github.com/llorllale/go-gitlint/releases/download/1.1.0/${GOLINT_FILENAME} --output ${GOLINT_FILENAME}
|
||||||
tar -zxv --directory .githooks/. -f ${GOLINT_FILENAME} gitlint
|
tar -zxv --directory .githooks/. -f ${GOLINT_FILENAME} gitlint
|
||||||
rm ${GOLINT_FILENAME}
|
rm ${GOLINT_FILENAME}
|
||||||
|
|
||||||
# Change to the frontend directory
|
# Change to the frontend directory
|
||||||
|
@ -17,7 +17,6 @@ printError() {
|
|||||||
printf "${RED}AppFlowy : $1${ENDCOLOR}\n"
|
printf "${RED}AppFlowy : $1${ENDCOLOR}\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Note: This script does not install applications which are installed by the package manager. There are too many package managers out there.
|
# Note: This script does not install applications which are installed by the package manager. There are too many package managers out there.
|
||||||
|
|
||||||
# Install Rust
|
# Install Rust
|
||||||
@ -46,9 +45,27 @@ else
|
|||||||
printSuccess "Rust has been detected on your system, so Rust installation has been skipped"
|
printSuccess "Rust has been detected on your system, so Rust installation has been skipped"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Enable the flutter stable channel
|
|
||||||
printMessage "Setting up Flutter"
|
printMessage "Setting up Flutter"
|
||||||
flutter channel stable
|
# Get the current Flutter version
|
||||||
|
FLUTTER_VERSION=$(flutter --version | grep -oP 'Flutter \K\S+')
|
||||||
|
# Check if the current version is 3.3.10
|
||||||
|
if [ "$FLUTTER_VERSION" = "3.3.10" ]; then
|
||||||
|
echo "Flutter version is already 3.3.10"
|
||||||
|
else
|
||||||
|
# Get the path to the Flutter SDK
|
||||||
|
FLUTTER_PATH=$(which flutter)
|
||||||
|
FLUTTER_PATH=${FLUTTER_PATH%/bin/flutter}
|
||||||
|
|
||||||
|
current_dir=$(pwd)
|
||||||
|
|
||||||
|
cd $FLUTTER_PATH
|
||||||
|
# Use git to checkout version 3.3.10 of Flutter
|
||||||
|
git checkout 3.3.10
|
||||||
|
# Get back to current working directory
|
||||||
|
cd "$current_dir"
|
||||||
|
|
||||||
|
echo "Switched to Flutter version 3.3.10"
|
||||||
|
fi
|
||||||
|
|
||||||
# Add pub cache and cargo to PATH
|
# Add pub cache and cargo to PATH
|
||||||
powershell '[Environment]::SetEnvironmentVariable("PATH", $Env:PATH + ";" + $Env:LOCALAPPDATA + "\Pub\Cache\Bin", [EnvironmentVariableTarget]::User)'
|
powershell '[Environment]::SetEnvironmentVariable("PATH", $Env:PATH + ";" + $Env:LOCALAPPDATA + "\Pub\Cache\Bin", [EnvironmentVariableTarget]::User)'
|
||||||
@ -64,14 +81,14 @@ flutter doctor
|
|||||||
printMessage "Setting up githooks."
|
printMessage "Setting up githooks."
|
||||||
git config core.hooksPath .githooks
|
git config core.hooksPath .githooks
|
||||||
|
|
||||||
# Install go-gitlint
|
# Install go-gitlint
|
||||||
printMessage "Installing go-gitlint."
|
printMessage "Installing go-gitlint."
|
||||||
GOLINT_FILENAME="go-gitlint_1.1.0_windows_x86_64.tar.gz"
|
GOLINT_FILENAME="go-gitlint_1.1.0_windows_x86_64.tar.gz"
|
||||||
if curl --proto '=https' --tlsv1.2 -sSfL https://github.com/llorllale/go-gitlint/releases/download/1.1.0/${GOLINT_FILENAME} -o ${GOLINT_FILENAME}; then
|
if curl --proto '=https' --tlsv1.2 -sSfL https://github.com/llorllale/go-gitlint/releases/download/1.1.0/${GOLINT_FILENAME} -o ${GOLINT_FILENAME}; then
|
||||||
tar -zxv --directory .githooks/. -f ${GOLINT_FILENAME} gitlint.exe
|
tar -zxv --directory .githooks/. -f ${GOLINT_FILENAME} gitlint.exe
|
||||||
rm ${GOLINT_FILENAME}
|
rm ${GOLINT_FILENAME}
|
||||||
else
|
else
|
||||||
printError "Failed to install go-gitlint"
|
printError "Failed to install go-gitlint"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Change to the frontend directory
|
# Change to the frontend directory
|
||||||
|
Loading…
x
Reference in New Issue
Block a user