mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: unpublish the page auto when moving it to another space
This commit is contained in:
parent
81f0100e78
commit
5be41553be
@ -6,7 +6,6 @@ import 'package:appflowy/plugins/document/presentation/share/pubish_color_extens
|
|||||||
import 'package:appflowy/plugins/document/presentation/share/publish_name_generator.dart';
|
import 'package:appflowy/plugins/document/presentation/share/publish_name_generator.dart';
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:appflowy/util/theme_extension.dart';
|
import 'package:appflowy/util/theme_extension.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/toast.dart';
|
|
||||||
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
@ -25,9 +24,15 @@ class PublishTab extends StatelessWidget {
|
|||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
if (state.publishResult != null) {
|
if (state.publishResult != null) {
|
||||||
state.publishResult!.fold(
|
state.publishResult!.fold(
|
||||||
(value) => showSnackBarMessage(context, 'Published successfully'),
|
(value) => showToastNotification(
|
||||||
(error) =>
|
context,
|
||||||
showSnackBarMessage(context, 'Failed to publish: $error'),
|
message: LocaleKeys.publish_publishSuccessfully.tr(),
|
||||||
|
),
|
||||||
|
(error) => showToastNotification(
|
||||||
|
context,
|
||||||
|
message:
|
||||||
|
'${LocaleKeys.publish_publishFailed.tr()}: ${error.code}',
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -140,12 +140,14 @@ class ViewBloc extends Bloc<ViewEvent, ViewState> {
|
|||||||
},
|
},
|
||||||
delete: (e) async {
|
delete: (e) async {
|
||||||
final result = await ViewBackendService.delete(viewId: view.id);
|
final result = await ViewBackendService.delete(viewId: view.id);
|
||||||
|
|
||||||
|
result.onSuccess((_) {
|
||||||
|
add(const ViewEvent.unpublish(sync: false));
|
||||||
|
});
|
||||||
|
|
||||||
emit(
|
emit(
|
||||||
result.fold(
|
result.fold(
|
||||||
(l) {
|
(l) {
|
||||||
// unpublish the page if it's published
|
|
||||||
unawaited(_unpublishPage(view));
|
|
||||||
|
|
||||||
return state.copyWith(
|
return state.copyWith(
|
||||||
successOrFailure: FlowyResult.success(null),
|
successOrFailure: FlowyResult.success(null),
|
||||||
);
|
);
|
||||||
@ -187,8 +189,11 @@ class ViewBloc extends Bloc<ViewEvent, ViewState> {
|
|||||||
);
|
);
|
||||||
emit(
|
emit(
|
||||||
result.fold(
|
result.fold(
|
||||||
(l) =>
|
(l) {
|
||||||
state.copyWith(successOrFailure: FlowyResult.success(null)),
|
return state.copyWith(
|
||||||
|
successOrFailure: FlowyResult.success(null),
|
||||||
|
);
|
||||||
|
},
|
||||||
(error) => state.copyWith(
|
(error) => state.copyWith(
|
||||||
successOrFailure: FlowyResult.failure(error),
|
successOrFailure: FlowyResult.failure(error),
|
||||||
),
|
),
|
||||||
@ -243,6 +248,13 @@ class ViewBloc extends Bloc<ViewEvent, ViewState> {
|
|||||||
}
|
}
|
||||||
add(const ViewEvent.setIsExpanded(false));
|
add(const ViewEvent.setIsExpanded(false));
|
||||||
},
|
},
|
||||||
|
unpublish: (value) async {
|
||||||
|
if (value.sync) {
|
||||||
|
await _unpublishPage(view);
|
||||||
|
} else {
|
||||||
|
unawaited(_unpublishPage(view));
|
||||||
|
}
|
||||||
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -390,14 +402,28 @@ class ViewBloc extends Bloc<ViewEvent, ViewState> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unpublish the page and all its child pages
|
||||||
Future<void> _unpublishPage(ViewPB view) async {
|
Future<void> _unpublishPage(ViewPB view) async {
|
||||||
final allChildViews = await _getAllChildViews(view);
|
final allChildViews = await _getAllChildViews(view);
|
||||||
final views = [view, ...allChildViews];
|
final views = [view, ...allChildViews];
|
||||||
|
|
||||||
// unpublish
|
// unpublish
|
||||||
for (final view in views) {
|
await Future.wait(
|
||||||
await ViewBackendService.unpublish(view);
|
views.map((view) => ViewBackendService.getPublishInfo(view)),
|
||||||
}
|
).then((results) {
|
||||||
|
final viewsToUnpublish = <ViewPB>[];
|
||||||
|
for (var i = 0; i < results.length; i++) {
|
||||||
|
final result = results[i];
|
||||||
|
if (result.isSuccess) {
|
||||||
|
viewsToUnpublish.add(views[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return viewsToUnpublish;
|
||||||
|
}).then((views) async {
|
||||||
|
await Future.wait(
|
||||||
|
views.map((view) => ViewBackendService.unpublish(view)),
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<ViewPB>> _getAllChildViews(ViewPB view) async {
|
Future<List<ViewPB>> _getAllChildViews(ViewPB view) async {
|
||||||
@ -468,6 +494,8 @@ class ViewEvent with _$ViewEvent {
|
|||||||
) = UpdateViewVisibility;
|
) = UpdateViewVisibility;
|
||||||
const factory ViewEvent.updateIcon(String? icon) = UpdateIcon;
|
const factory ViewEvent.updateIcon(String? icon) = UpdateIcon;
|
||||||
const factory ViewEvent.collapseAllPages() = CollapseAllPages;
|
const factory ViewEvent.collapseAllPages() = CollapseAllPages;
|
||||||
|
// this event will unpublish the page and all its child pages if they are published
|
||||||
|
const factory ViewEvent.unpublish({required bool sync}) = Unpublish;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
|
@ -11,6 +11,8 @@ 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';
|
||||||
|
|
||||||
|
typedef MovePageMenuOnSelected = void Function(ViewPB space, ViewPB view);
|
||||||
|
|
||||||
class MovePageMenu extends StatefulWidget {
|
class MovePageMenu extends StatefulWidget {
|
||||||
const MovePageMenu({
|
const MovePageMenu({
|
||||||
super.key,
|
super.key,
|
||||||
@ -23,7 +25,7 @@ class MovePageMenu extends StatefulWidget {
|
|||||||
final ViewPB sourceView;
|
final ViewPB sourceView;
|
||||||
final UserProfilePB userProfile;
|
final UserProfilePB userProfile;
|
||||||
final String workspaceId;
|
final String workspaceId;
|
||||||
final void Function(ViewPB view) onSelected;
|
final MovePageMenuOnSelected onSelected;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<MovePageMenu> createState() => _MovePageMenuState();
|
State<MovePageMenu> createState() => _MovePageMenuState();
|
||||||
@ -88,7 +90,7 @@ class _MovePageMenuState extends State<MovePageMenu> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: _buildGroupedViews(state.queryResults!),
|
child: _buildGroupedViews(space, state.queryResults!),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -99,7 +101,7 @@ class _MovePageMenuState extends State<MovePageMenu> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildGroupedViews(List<ViewPB> views) {
|
Widget _buildGroupedViews(ViewPB space, List<ViewPB> views) {
|
||||||
final groupedViews = views
|
final groupedViews = views
|
||||||
.where(
|
.where(
|
||||||
(view) =>
|
(view) =>
|
||||||
@ -108,7 +110,7 @@ class _MovePageMenuState extends State<MovePageMenu> {
|
|||||||
.toList();
|
.toList();
|
||||||
return _MovePageGroupedViews(
|
return _MovePageGroupedViews(
|
||||||
views: groupedViews,
|
views: groupedViews,
|
||||||
onSelected: widget.onSelected,
|
onSelected: (view) => widget.onSelected(space, view),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +126,7 @@ class _MovePageMenuState extends State<MovePageMenu> {
|
|||||||
child: CurrentSpace(
|
child: CurrentSpace(
|
||||||
onTapBlankArea: () {
|
onTapBlankArea: () {
|
||||||
// move the page to current space
|
// move the page to current space
|
||||||
widget.onSelected(space);
|
widget.onSelected(space, space);
|
||||||
},
|
},
|
||||||
space: space,
|
space: space,
|
||||||
),
|
),
|
||||||
@ -145,7 +147,7 @@ class _MovePageMenuState extends State<MovePageMenu> {
|
|||||||
disableSelectedStatus: true,
|
disableSelectedStatus: true,
|
||||||
// hide the ... and + buttons
|
// hide the ... and + buttons
|
||||||
rightIconsBuilder: (context, view) => [],
|
rightIconsBuilder: (context, view) => [],
|
||||||
onSelected: (_, view) => widget.onSelected(view),
|
onSelected: (_, view) => widget.onSelected(space, view),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -7,6 +7,7 @@ import 'package:appflowy/startup/startup.dart';
|
|||||||
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
|
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/sidebar/folder/folder_bloc.dart';
|
import 'package:appflowy/workspace/application/sidebar/folder/folder_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/sidebar/rename_view/rename_view_bloc.dart';
|
import 'package:appflowy/workspace/application/sidebar/rename_view/rename_view_bloc.dart';
|
||||||
|
import 'package:appflowy/workspace/application/sidebar/space/space_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
|
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/view/prelude.dart';
|
import 'package:appflowy/workspace/application/view/prelude.dart';
|
||||||
import 'package:appflowy/workspace/application/view/view_ext.dart';
|
import 'package:appflowy/workspace/application/view/view_ext.dart';
|
||||||
@ -20,9 +21,10 @@ import 'package:appflowy/workspace/presentation/home/menu/view/view_add_button.d
|
|||||||
import 'package:appflowy/workspace/presentation/home/menu/view/view_more_action_button.dart';
|
import 'package:appflowy/workspace/presentation/home/menu/view/view_more_action_button.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/rename_view_popover.dart';
|
import 'package:appflowy/workspace/presentation/widgets/rename_view_popover.dart';
|
||||||
|
import 'package:appflowy_backend/log.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
|
||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
@ -337,6 +339,7 @@ class _InnerViewItemState extends State<InnerViewItem> {
|
|||||||
onMove: widget.isPlaceholder
|
onMove: widget.isPlaceholder
|
||||||
? (from, to) => _moveViewCrossSection(
|
? (from, to) => _moveViewCrossSection(
|
||||||
context,
|
context,
|
||||||
|
null,
|
||||||
widget.view,
|
widget.view,
|
||||||
widget.parentView,
|
widget.parentView,
|
||||||
widget.spaceType,
|
widget.spaceType,
|
||||||
@ -749,12 +752,15 @@ class _SingleInnerViewItemState extends State<SingleInnerViewItem> {
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case ViewMoreActionType.moveTo:
|
case ViewMoreActionType.moveTo:
|
||||||
final target = data;
|
final value = data;
|
||||||
if (target is! ViewPB) {
|
if (value is! (ViewPB, ViewPB)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
final space = value.$1;
|
||||||
|
final target = value.$2;
|
||||||
_moveViewCrossSection(
|
_moveViewCrossSection(
|
||||||
context,
|
context,
|
||||||
|
space,
|
||||||
widget.view,
|
widget.view,
|
||||||
widget.parentView,
|
widget.parentView,
|
||||||
widget.spaceType,
|
widget.spaceType,
|
||||||
@ -839,6 +845,7 @@ bool isReferencedDatabaseView(ViewPB view, ViewPB? parentView) {
|
|||||||
|
|
||||||
void _moveViewCrossSection(
|
void _moveViewCrossSection(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
|
ViewPB? toSpace,
|
||||||
ViewPB view,
|
ViewPB view,
|
||||||
ViewPB? parentView,
|
ViewPB? parentView,
|
||||||
FolderSpaceType spaceType,
|
FolderSpaceType spaceType,
|
||||||
@ -859,6 +866,17 @@ void _moveViewCrossSection(
|
|||||||
final toSection = spaceType == FolderSpaceType.public
|
final toSection = spaceType == FolderSpaceType.public
|
||||||
? ViewSectionPB.Public
|
? ViewSectionPB.Public
|
||||||
: ViewSectionPB.Private;
|
: ViewSectionPB.Private;
|
||||||
|
|
||||||
|
final currentSpace = context.read<SpaceBloc>().state.currentSpace;
|
||||||
|
if (currentSpace != null &&
|
||||||
|
toSpace != null &&
|
||||||
|
currentSpace.id != toSpace.id) {
|
||||||
|
Log.info(
|
||||||
|
'Move view(${from.name}) to another space(${toSpace.name}), unpublish the view',
|
||||||
|
);
|
||||||
|
context.read<ViewBloc>().add(const ViewEvent.unpublish(sync: false));
|
||||||
|
}
|
||||||
|
|
||||||
context.read<ViewBloc>().add(
|
context.read<ViewBloc>().add(
|
||||||
ViewEvent.move(
|
ViewEvent.move(
|
||||||
from,
|
from,
|
||||||
|
@ -192,8 +192,8 @@ class ViewMoreActionTypeWrapper extends CustomActionCell {
|
|||||||
sourceView: sourceView,
|
sourceView: sourceView,
|
||||||
userProfile: userProfile,
|
userProfile: userProfile,
|
||||||
workspaceId: workspaceId,
|
workspaceId: workspaceId,
|
||||||
onSelected: (view) {
|
onSelected: (space, view) {
|
||||||
onTap(controller, view);
|
onTap(controller, (space, view));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -107,8 +107,8 @@
|
|||||||
"clipboard": "Copy to clipboard",
|
"clipboard": "Copy to clipboard",
|
||||||
"csv": "CSV",
|
"csv": "CSV",
|
||||||
"copyLink": "Copy Link",
|
"copyLink": "Copy Link",
|
||||||
"publishToTheWeb": "Publish to the web",
|
"publishToTheWeb": "Publish to Web",
|
||||||
"publishToTheWebHint": "Publish a static website of this page",
|
"publishToTheWebHint": "Create a website with AppFlowy",
|
||||||
"publish": "Publish",
|
"publish": "Publish",
|
||||||
"unPublish": "Unpublish",
|
"unPublish": "Unpublish",
|
||||||
"visitSite": "Visit site"
|
"visitSite": "Visit site"
|
||||||
@ -2051,6 +2051,9 @@
|
|||||||
"imageBlock": "The image link has been copied to the clipboard",
|
"imageBlock": "The image link has been copied to the clipboard",
|
||||||
"mathBlock": "The math equation has been copied to the clipboard"
|
"mathBlock": "The math equation has been copied to the clipboard"
|
||||||
},
|
},
|
||||||
"containsPublishedPage": "This page contains one or more published page, it will be unpublished if you continue."
|
"containsPublishedPage": "This page contains one or more published page, it will be unpublished if you continue.",
|
||||||
|
"publishSuccessfully": "Published successfully",
|
||||||
|
"unpublishSuccessfully": "Unpublished successfully",
|
||||||
|
"publishFailed": "Failed to publish"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user