mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-07-23 17:11:23 +00:00

* feat: support a event for getting encoded collab of document * feat: support publish view and unpublish views * feat: publish page to the web * chore: refacotor share bloc * feat: call the publish event * feat: support publish view and unpublish views * feat: integrate publish api * feat: integrate unpublish api * feat: fetch the publish info to show the publish status * feat: support publish interfaces * fix: lint error * fix: modified web server * fix: some style * fix: some style * fix: some style * fix: some style * fix: some style * fix: some style * fix: some style * fix: some style * fix: some style * fix: update codes * fix: update codes * fix: update codes * fix: update codes * fix: update codes * chore: refactor publish bloc * fix: some style * fix: some style * fix: some style * fix: some style * fix: some style * fix: some style * fix: the name is too long to publish * chore: change color * fix: some style * fix: some style * feat: refacotor share menu UI * fix: some style * fix: lint * fix: some style * feat: refacotor export-as * fix: some style * chore: refactor share menu colors * fix: rust ci * fix: some style * fix: some style * fix: deploy * fix: deploy * fix: deploy * fix: deploy * fix: deploy * fix: deploy * fix: deploy * fix: deploy * fix: deploy * fix: deploy * fix: deploy * fix: deploy * fix: bugs * fix: bugs * fix: bugs * fix: bugs * fix: bugs * fix: bugs * fix: bugs * fix: bugs * fix: bugs * fix: bugs * fix: bugs * fix: bugs * fix: bugs * fix: bugs * fix: bugs * fix: bugs * fix: rerelease * fix: deploy * fix: deploy * fix: deploy * fix: deploy * fix: deploy * fix: deploy * fix: deploy * fix: og image * fix: support copy button * fix: support copy button * fix: support copy button * chore: add a params * feat: use default publish name * chore: update copy * feat: show a confirm deletion dialog if the deleted page contains published page * feat: add copy toast in publish tab * fix: to 404 fix: to 404 fix: to 404 fix: the error to 404 * feat: unpublish the page auto when moving it to another space * feat: improve confirm deletion dialog * feat: show unpublish error * chore: use beta.appflowy.com * feat: disable publish in non-apppflowy-cloud user mode * fix: modified bullted icon style * fix: the dark mode color * fix: save the dark mode in local storage * fix: text color * chore: make bash script more portable (#5679) * fix: title longer * chore: move the files and modified the en * chore: update deploy.sh * chore: modified Dockerfile * chore: modified server.cjs to server.js * chore: modifed server.js to server.ts * chore: replace publish url * chore: remove todo list hover * chore: show confirm dialog before deleting page * fix: unpublish the pages before deleting * fix: table cell bg color * fix: callout icon * fix: list number * fix: emoji * fix: number icon * fix: callout icon position * fix: add margin bottom * fix: code block * fix: support scroll for breadcrumbs * fix: the breadcrumb doesn't update after moving page * fix: 0705 issues * fix: update publish status afer deleting page * chore: add hover effect for visit site button * fix: remove puiblish url text field enable border color * chore: update delete page copy * chore: enable debug category * fix: only render sidebar if the spaces are ready * fix: the breadcrumb doesn't update after moving page * fix: auto code * fix: add emoji * fix: add emoji * fix: favicon * fix: cypress test * fix: remove deploy ci * fix: default url * chore: revert launch.json * fix: docker ci * fix: change favicon * fix: flutter integration test * feat: add hover effect to share menu * chore: add a checkmark if the page has been published * chore: revert space deletion --------- Co-authored-by: Lucas.Xu <lucas.xu@appflowy.io> Co-authored-by: Zack <speed2exe@live.com.sg>
342 lines
9.2 KiB
Dart
342 lines
9.2 KiB
Dart
import 'package:appflowy/generated/locale_keys.g.dart';
|
|
import 'package:appflowy/startup/tasks/app_widget.dart';
|
|
import 'package:appflowy/workspace/presentation/home/menu/sidebar/space/shared_widget.dart';
|
|
import 'package:easy_localization/easy_localization.dart';
|
|
import 'package:flowy_infra/size.dart';
|
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
|
import 'package:flowy_infra_ui/style_widget/text_input.dart';
|
|
import 'package:flowy_infra_ui/widget/buttons/primary_button.dart';
|
|
import 'package:flowy_infra_ui/widget/buttons/secondary_button.dart';
|
|
import 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart';
|
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:toastification/toastification.dart';
|
|
|
|
export 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart';
|
|
|
|
class NavigatorTextFieldDialog extends StatefulWidget {
|
|
const NavigatorTextFieldDialog({
|
|
super.key,
|
|
required this.title,
|
|
this.autoSelectAllText = false,
|
|
required this.value,
|
|
required this.onConfirm,
|
|
this.onCancel,
|
|
this.maxLength,
|
|
this.hintText,
|
|
});
|
|
|
|
final String value;
|
|
final String title;
|
|
final VoidCallback? onCancel;
|
|
final void Function(String, BuildContext) onConfirm;
|
|
final bool autoSelectAllText;
|
|
final int? maxLength;
|
|
final String? hintText;
|
|
|
|
@override
|
|
State<NavigatorTextFieldDialog> createState() =>
|
|
_NavigatorTextFieldDialogState();
|
|
}
|
|
|
|
class _NavigatorTextFieldDialogState extends State<NavigatorTextFieldDialog> {
|
|
String newValue = "";
|
|
final controller = TextEditingController();
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
newValue = widget.value;
|
|
controller.text = newValue;
|
|
if (widget.autoSelectAllText) {
|
|
controller.selection = TextSelection(
|
|
baseOffset: 0,
|
|
extentOffset: newValue.length,
|
|
);
|
|
}
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
controller.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return StyledDialog(
|
|
child: Column(
|
|
children: <Widget>[
|
|
FlowyText.medium(
|
|
widget.title,
|
|
color: Theme.of(context).colorScheme.tertiary,
|
|
fontSize: FontSizes.s16,
|
|
),
|
|
VSpace(Insets.m),
|
|
FlowyFormTextInput(
|
|
hintText:
|
|
widget.hintText ?? LocaleKeys.dialogCreatePageNameHint.tr(),
|
|
controller: controller,
|
|
textStyle: Theme.of(context)
|
|
.textTheme
|
|
.bodySmall
|
|
?.copyWith(fontSize: FontSizes.s16),
|
|
maxLength: widget.maxLength,
|
|
showCounter: false,
|
|
autoFocus: true,
|
|
onChanged: (text) {
|
|
newValue = text;
|
|
},
|
|
onEditingComplete: () {
|
|
widget.onConfirm(newValue, context);
|
|
AppGlobals.nav.pop();
|
|
},
|
|
),
|
|
VSpace(Insets.xl),
|
|
OkCancelButton(
|
|
onOkPressed: () {
|
|
widget.onConfirm(newValue, context);
|
|
Navigator.of(context).pop();
|
|
},
|
|
onCancelPressed: () {
|
|
widget.onCancel?.call();
|
|
Navigator.of(context).pop();
|
|
},
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class NavigatorAlertDialog extends StatefulWidget {
|
|
const NavigatorAlertDialog({
|
|
super.key,
|
|
required this.title,
|
|
this.cancel,
|
|
this.confirm,
|
|
this.hideCancelButton = false,
|
|
this.constraints,
|
|
});
|
|
|
|
final String title;
|
|
final void Function()? cancel;
|
|
final void Function()? confirm;
|
|
final bool hideCancelButton;
|
|
final BoxConstraints? constraints;
|
|
|
|
@override
|
|
State<NavigatorAlertDialog> createState() => _CreateFlowyAlertDialog();
|
|
}
|
|
|
|
class _CreateFlowyAlertDialog extends State<NavigatorAlertDialog> {
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return StyledDialog(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: <Widget>[
|
|
...[
|
|
ConstrainedBox(
|
|
constraints: widget.constraints ??
|
|
const BoxConstraints(
|
|
maxWidth: 400,
|
|
maxHeight: 260,
|
|
),
|
|
child: FlowyText.medium(
|
|
widget.title,
|
|
fontSize: FontSizes.s16,
|
|
textAlign: TextAlign.center,
|
|
color: Theme.of(context).colorScheme.tertiary,
|
|
maxLines: null,
|
|
),
|
|
),
|
|
],
|
|
if (widget.confirm != null) ...[
|
|
const VSpace(20),
|
|
OkCancelButton(
|
|
onOkPressed: () {
|
|
widget.confirm?.call();
|
|
Navigator.of(context).pop();
|
|
},
|
|
onCancelPressed: widget.hideCancelButton
|
|
? null
|
|
: () {
|
|
widget.cancel?.call();
|
|
Navigator.of(context).pop();
|
|
},
|
|
),
|
|
],
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class NavigatorOkCancelDialog extends StatelessWidget {
|
|
const NavigatorOkCancelDialog({
|
|
super.key,
|
|
this.onOkPressed,
|
|
this.onCancelPressed,
|
|
this.okTitle,
|
|
this.cancelTitle,
|
|
this.title,
|
|
this.message,
|
|
this.maxWidth,
|
|
});
|
|
|
|
final VoidCallback? onOkPressed;
|
|
final VoidCallback? onCancelPressed;
|
|
final String? okTitle;
|
|
final String? cancelTitle;
|
|
final String? title;
|
|
final String? message;
|
|
final double? maxWidth;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return StyledDialog(
|
|
maxWidth: maxWidth ?? 500,
|
|
padding: EdgeInsets.symmetric(horizontal: Insets.xl, vertical: Insets.l),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: <Widget>[
|
|
if (title != null) ...[
|
|
FlowyText.medium(
|
|
title!.toUpperCase(),
|
|
fontSize: FontSizes.s16,
|
|
maxLines: 3,
|
|
),
|
|
VSpace(Insets.sm * 1.5),
|
|
Container(
|
|
color: Theme.of(context).colorScheme.surfaceContainerHighest,
|
|
height: 1,
|
|
),
|
|
VSpace(Insets.m * 1.5),
|
|
],
|
|
if (message != null)
|
|
FlowyText.medium(
|
|
message!,
|
|
maxLines: 3,
|
|
),
|
|
SizedBox(height: Insets.l),
|
|
OkCancelButton(
|
|
onOkPressed: () {
|
|
onOkPressed?.call();
|
|
Navigator.of(context).pop();
|
|
},
|
|
onCancelPressed: () {
|
|
onCancelPressed?.call();
|
|
Navigator.of(context).pop();
|
|
},
|
|
okTitle: okTitle?.toUpperCase(),
|
|
cancelTitle: cancelTitle?.toUpperCase(),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class OkCancelButton extends StatelessWidget {
|
|
const OkCancelButton({
|
|
super.key,
|
|
this.onOkPressed,
|
|
this.onCancelPressed,
|
|
this.okTitle,
|
|
this.cancelTitle,
|
|
this.minHeight,
|
|
this.alignment = MainAxisAlignment.spaceAround,
|
|
this.mode = TextButtonMode.big,
|
|
});
|
|
|
|
final VoidCallback? onOkPressed;
|
|
final VoidCallback? onCancelPressed;
|
|
final String? okTitle;
|
|
final String? cancelTitle;
|
|
final double? minHeight;
|
|
final MainAxisAlignment alignment;
|
|
final TextButtonMode mode;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return SizedBox(
|
|
height: 48,
|
|
child: Row(
|
|
mainAxisAlignment: alignment,
|
|
children: <Widget>[
|
|
if (onCancelPressed != null)
|
|
SecondaryTextButton(
|
|
cancelTitle ?? LocaleKeys.button_cancel.tr(),
|
|
onPressed: onCancelPressed,
|
|
mode: mode,
|
|
),
|
|
if (onCancelPressed != null) HSpace(Insets.m),
|
|
if (onOkPressed != null)
|
|
PrimaryTextButton(
|
|
okTitle ?? LocaleKeys.button_ok.tr(),
|
|
onPressed: onOkPressed,
|
|
mode: mode,
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
void showToastNotification(
|
|
BuildContext context, {
|
|
required String message,
|
|
String? description,
|
|
}) {
|
|
toastification.show(
|
|
context: context,
|
|
type: ToastificationType.success,
|
|
style: ToastificationStyle.flat,
|
|
title: FlowyText(message),
|
|
description: description != null
|
|
? FlowyText.regular(
|
|
description,
|
|
fontSize: 12,
|
|
lineHeight: 1.2,
|
|
maxLines: 3,
|
|
)
|
|
: null,
|
|
alignment: Alignment.bottomCenter,
|
|
autoCloseDuration: const Duration(milliseconds: 3000),
|
|
showProgressBar: false,
|
|
backgroundColor: Theme.of(context).colorScheme.surface,
|
|
borderSide: BorderSide(
|
|
color: Colors.grey.withOpacity(0.4),
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<void> showConfirmDeletionDialog({
|
|
required BuildContext context,
|
|
required String name,
|
|
required String description,
|
|
required VoidCallback onConfirm,
|
|
}) {
|
|
return showDialog(
|
|
context: context,
|
|
builder: (_) {
|
|
final title = LocaleKeys.space_deleteConfirmation.tr() + name;
|
|
return Dialog(
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(12.0),
|
|
),
|
|
child: SizedBox(
|
|
width: 440,
|
|
child: ConfirmDeletionPopup(
|
|
title: title,
|
|
description: description,
|
|
onConfirm: onConfirm,
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|