mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: select cover image on upload (#3488)
This commit is contained in:
parent
2c757e9b6c
commit
048434024b
@ -41,36 +41,6 @@ class ChangeCoverPopover extends StatefulWidget {
|
||||
State<ChangeCoverPopover> createState() => _ChangeCoverPopoverState();
|
||||
}
|
||||
|
||||
class ColorOption {
|
||||
final String colorHex;
|
||||
|
||||
final String name;
|
||||
const ColorOption({
|
||||
required this.colorHex,
|
||||
required this.name,
|
||||
});
|
||||
}
|
||||
|
||||
class CoverColorPicker extends StatefulWidget {
|
||||
final String? selectedBackgroundColorHex;
|
||||
|
||||
final Color pickerBackgroundColor;
|
||||
final Color pickerItemHoverColor;
|
||||
final void Function(String color) onSubmittedBackgroundColorHex;
|
||||
final List<ColorOption> backgroundColorOptions;
|
||||
const CoverColorPicker({
|
||||
super.key,
|
||||
this.selectedBackgroundColorHex,
|
||||
required this.pickerBackgroundColor,
|
||||
required this.backgroundColorOptions,
|
||||
required this.pickerItemHoverColor,
|
||||
required this.onSubmittedBackgroundColorHex,
|
||||
});
|
||||
|
||||
@override
|
||||
State<CoverColorPicker> createState() => _CoverColorPickerState();
|
||||
}
|
||||
|
||||
class _ChangeCoverPopoverState extends State<ChangeCoverPopover> {
|
||||
bool isAddingImage = false;
|
||||
|
||||
@ -81,7 +51,15 @@ class _ChangeCoverPopoverState extends State<ChangeCoverPopover> {
|
||||
editorState: widget.editorState,
|
||||
node: widget.node,
|
||||
)..add(const ChangeCoverPopoverEvent.fetchPickedImagePaths()),
|
||||
child: BlocBuilder<ChangeCoverPopoverBloc, ChangeCoverPopoverState>(
|
||||
child: BlocConsumer<ChangeCoverPopoverBloc, ChangeCoverPopoverState>(
|
||||
listener: (context, state) {
|
||||
if (state is Loaded && state.selectLatestImage) {
|
||||
widget.onCoverChanged(
|
||||
CoverType.file,
|
||||
state.imageNames.last,
|
||||
);
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
@ -91,14 +69,15 @@ class _ChangeCoverPopoverState extends State<ChangeCoverPopover> {
|
||||
onBackPressed: () => setState(() {
|
||||
isAddingImage = false;
|
||||
}),
|
||||
onFileSubmit: (List<String> path) {
|
||||
onFileSubmit: (_) {
|
||||
context.read<ChangeCoverPopoverBloc>().add(
|
||||
const ChangeCoverPopoverEvent
|
||||
.fetchPickedImagePaths(),
|
||||
.fetchPickedImagePaths(
|
||||
selectLatestImage: true,
|
||||
),
|
||||
);
|
||||
setState(() {
|
||||
isAddingImage = false;
|
||||
});
|
||||
|
||||
setState(() => isAddingImage = false);
|
||||
},
|
||||
)
|
||||
: _buildCoverSelection(),
|
||||
@ -294,7 +273,8 @@ class _ChangeCoverPopoverState extends State<ChangeCoverPopover> {
|
||||
},
|
||||
);
|
||||
}
|
||||
return Container();
|
||||
|
||||
return const SizedBox.shrink();
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -314,6 +294,7 @@ class _ChangeCoverPopoverState extends State<ChangeCoverPopover> {
|
||||
@visibleForTesting
|
||||
class NewCustomCoverButton extends StatelessWidget {
|
||||
final VoidCallback onPressed;
|
||||
|
||||
const NewCustomCoverButton({super.key, required this.onPressed});
|
||||
|
||||
@override
|
||||
@ -337,6 +318,85 @@ class NewCustomCoverButton extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class ColorOption {
|
||||
final String colorHex;
|
||||
|
||||
final String name;
|
||||
const ColorOption({
|
||||
required this.colorHex,
|
||||
required this.name,
|
||||
});
|
||||
}
|
||||
|
||||
class CoverColorPicker extends StatefulWidget {
|
||||
final String? selectedBackgroundColorHex;
|
||||
|
||||
final Color pickerBackgroundColor;
|
||||
final Color pickerItemHoverColor;
|
||||
final void Function(String color) onSubmittedBackgroundColorHex;
|
||||
final List<ColorOption> backgroundColorOptions;
|
||||
const CoverColorPicker({
|
||||
super.key,
|
||||
this.selectedBackgroundColorHex,
|
||||
required this.pickerBackgroundColor,
|
||||
required this.backgroundColorOptions,
|
||||
required this.pickerItemHoverColor,
|
||||
required this.onSubmittedBackgroundColorHex,
|
||||
});
|
||||
|
||||
@override
|
||||
State<CoverColorPicker> createState() => _CoverColorPickerState();
|
||||
}
|
||||
|
||||
class _CoverColorPickerState extends State<CoverColorPicker> {
|
||||
final scrollController = ScrollController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: 30,
|
||||
alignment: Alignment.center,
|
||||
child: ScrollConfiguration(
|
||||
behavior: ScrollConfiguration.of(context).copyWith(
|
||||
dragDevices: {
|
||||
PointerDeviceKind.touch,
|
||||
PointerDeviceKind.mouse,
|
||||
},
|
||||
platform: TargetPlatform.windows,
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
child: _buildColorItems(
|
||||
widget.backgroundColorOptions,
|
||||
widget.selectedBackgroundColorHex,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
scrollController.dispose();
|
||||
}
|
||||
|
||||
Widget _buildColorItems(List<ColorOption> options, String? selectedColor) {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: options
|
||||
.map(
|
||||
(e) => ColorItem(
|
||||
option: e,
|
||||
isChecked: e.colorHex == selectedColor,
|
||||
hoverColor: widget.pickerItemHoverColor,
|
||||
onTap: widget.onSubmittedBackgroundColorHex,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class DeleteImageAlertDialog extends StatelessWidget {
|
||||
const DeleteImageAlertDialog({
|
||||
Key? key,
|
||||
@ -458,55 +518,6 @@ class _ImageGridItemState extends State<ImageGridItem> {
|
||||
}
|
||||
}
|
||||
|
||||
class _CoverColorPickerState extends State<CoverColorPicker> {
|
||||
final scrollController = ScrollController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: 30,
|
||||
alignment: Alignment.center,
|
||||
child: ScrollConfiguration(
|
||||
behavior: ScrollConfiguration.of(context).copyWith(
|
||||
dragDevices: {
|
||||
PointerDeviceKind.touch,
|
||||
PointerDeviceKind.mouse,
|
||||
},
|
||||
platform: TargetPlatform.windows,
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
child: _buildColorItems(
|
||||
widget.backgroundColorOptions,
|
||||
widget.selectedBackgroundColorHex,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
scrollController.dispose();
|
||||
}
|
||||
|
||||
Widget _buildColorItems(List<ColorOption> options, String? selectedColor) {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: options
|
||||
.map(
|
||||
(e) => ColorItem(
|
||||
option: e,
|
||||
isChecked: e.colorHex == selectedColor,
|
||||
hoverColor: widget.pickerItemHoverColor,
|
||||
onTap: widget.onSubmittedBackgroundColorHex,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
class ColorItem extends StatelessWidget {
|
||||
final ColorOption option;
|
||||
|
@ -16,18 +16,28 @@ class ChangeCoverPopoverBloc
|
||||
final Node node;
|
||||
late final SharedPreferences _prefs;
|
||||
final _initCompleter = Completer<void>();
|
||||
ChangeCoverPopoverBloc({required this.editorState, required this.node})
|
||||
: super(const ChangeCoverPopoverState.initial()) {
|
||||
|
||||
ChangeCoverPopoverBloc({
|
||||
required this.editorState,
|
||||
required this.node,
|
||||
}) : super(const ChangeCoverPopoverState.initial()) {
|
||||
SharedPreferences.getInstance().then((prefs) {
|
||||
_prefs = prefs;
|
||||
_initCompleter.complete();
|
||||
});
|
||||
|
||||
on<ChangeCoverPopoverEvent>((event, emit) async {
|
||||
await event.map(
|
||||
fetchPickedImagePaths:
|
||||
(FetchPickedImagePaths fetchPickedImagePaths) async {
|
||||
final imageNames = await _getPreviouslyPickedImagePaths();
|
||||
emit(ChangeCoverPopoverState.loaded(imageNames));
|
||||
|
||||
emit(
|
||||
ChangeCoverPopoverState.loaded(
|
||||
imageNames,
|
||||
selectLatestImage: fetchPickedImagePaths.selectLatestImage,
|
||||
),
|
||||
);
|
||||
},
|
||||
deleteImage: (DeleteImage deleteImage) async {
|
||||
final currentState = state;
|
||||
@ -100,8 +110,9 @@ class ChangeCoverPopoverBloc
|
||||
|
||||
@freezed
|
||||
class ChangeCoverPopoverEvent with _$ChangeCoverPopoverEvent {
|
||||
const factory ChangeCoverPopoverEvent.fetchPickedImagePaths() =
|
||||
FetchPickedImagePaths;
|
||||
const factory ChangeCoverPopoverEvent.fetchPickedImagePaths({
|
||||
@Default(false) bool selectLatestImage,
|
||||
}) = FetchPickedImagePaths;
|
||||
|
||||
const factory ChangeCoverPopoverEvent.deleteImage(String path) = DeleteImage;
|
||||
const factory ChangeCoverPopoverEvent.clearAllImages() = ClearAllImages;
|
||||
@ -112,6 +123,7 @@ class ChangeCoverPopoverState with _$ChangeCoverPopoverState {
|
||||
const factory ChangeCoverPopoverState.initial() = Initial;
|
||||
const factory ChangeCoverPopoverState.loading() = Loading;
|
||||
const factory ChangeCoverPopoverState.loaded(
|
||||
List<String> imageNames,
|
||||
) = Loaded;
|
||||
List<String> imageNames, {
|
||||
@Default(false) selectLatestImage,
|
||||
}) = Loaded;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user