mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: the name is too long to publish
This commit is contained in:
parent
e51b0f90de
commit
2f9f2c1ba7
8
frontend/.vscode/launch.json
vendored
8
frontend/.vscode/launch.json
vendored
@ -116,11 +116,11 @@
|
||||
{
|
||||
"name": "AF-desktop: Debug Rust",
|
||||
"type": "lldb",
|
||||
"request": "attach",
|
||||
"pid": "${command:pickMyProcess}"
|
||||
// "request": "attach",
|
||||
// "pid": "${command:pickMyProcess}"
|
||||
// To launch the application directly, use the following configuration:
|
||||
// "request": "launch",
|
||||
// "program": "[YOUR_APPLICATION_PATH]",
|
||||
"request": "launch",
|
||||
"program": "/Users/lucas.xu/Desktop/development/AppFlowy/frontend/appflowy_flutter/build/macos/Build/Products/Debug/AppFlowy.app",
|
||||
},
|
||||
{
|
||||
// https://tauri.app/v1/guides/debugging/vs-code
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:appflowy/workspace/application/export/document_exporter.dart';
|
||||
import 'package:appflowy/workspace/application/view/view_listener.dart';
|
||||
import 'package:appflowy/workspace/application/view/view_service.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-document/entities.pb.dart';
|
||||
@ -12,7 +13,7 @@ import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'document_share_bloc.freezed.dart';
|
||||
|
||||
const _url = 'https://test.appflowy.io';
|
||||
const _url = 'https://test.appflowy.com';
|
||||
|
||||
class DocumentShareBloc extends Bloc<DocumentShareEvent, DocumentShareState> {
|
||||
DocumentShareBloc({
|
||||
@ -21,16 +22,30 @@ class DocumentShareBloc extends Bloc<DocumentShareEvent, DocumentShareState> {
|
||||
on<DocumentShareEvent>((event, emit) async {
|
||||
await event.when(
|
||||
initial: () async {
|
||||
viewListener = ViewListener(viewId: view.id)
|
||||
..start(
|
||||
onViewUpdated: (value) {
|
||||
add(DocumentShareEvent.updateViewName(value.name));
|
||||
},
|
||||
);
|
||||
|
||||
final publishInfo = await ViewBackendService.getPublishInfo(view);
|
||||
publishInfo.fold((s) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
isPublished: true,
|
||||
url: '$_url/${s.namespace}/${s.publishName}',
|
||||
viewName: view.name,
|
||||
),
|
||||
);
|
||||
}, (f) {
|
||||
emit(state.copyWith(isPublished: false, url: ''));
|
||||
emit(
|
||||
state.copyWith(
|
||||
isPublished: false,
|
||||
url: '',
|
||||
viewName: view.name,
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
share: (type, path) async {
|
||||
@ -101,14 +116,24 @@ class DocumentShareBloc extends Bloc<DocumentShareEvent, DocumentShareState> {
|
||||
),
|
||||
);
|
||||
},
|
||||
updateViewName: (viewName) async {
|
||||
emit(state.copyWith(viewName: viewName));
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
final ViewPB view;
|
||||
late final ViewListener viewListener;
|
||||
|
||||
late final exporter = DocumentExporter(view);
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
await viewListener.stop();
|
||||
return super.close();
|
||||
}
|
||||
|
||||
Future<FlowyResult<ExportDataPB, FlowyError>> _export(
|
||||
DocumentShareType type,
|
||||
String? path,
|
||||
@ -181,6 +206,8 @@ class DocumentShareEvent with _$DocumentShareEvent {
|
||||
String pageId,
|
||||
) = _Publish;
|
||||
const factory DocumentShareEvent.unPublish() = _UnPublish;
|
||||
const factory DocumentShareEvent.updateViewName(String name) =
|
||||
_UpdateViewName;
|
||||
}
|
||||
|
||||
@freezed
|
||||
@ -191,11 +218,13 @@ class DocumentShareState with _$DocumentShareState {
|
||||
required bool isPublished,
|
||||
FlowyResult<void, FlowyError>? publishResult,
|
||||
required String url,
|
||||
required String viewName,
|
||||
}) = _DocumentShareState;
|
||||
|
||||
factory DocumentShareState.initial() => const DocumentShareState(
|
||||
isLoading: false,
|
||||
isPublished: false,
|
||||
url: '',
|
||||
viewName: '',
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flowy_infra/uuid.dart';
|
||||
|
||||
final _regExp = RegExp(r'[^\w\-\.@:/]');
|
||||
|
||||
Future<String> generateNameSpace() async {
|
||||
const workspaceName = '';
|
||||
final id = uuid().substring(0, 8);
|
||||
return '$workspaceName$id'.replaceAll(_regExp, '-');
|
||||
}
|
||||
|
||||
// The backend limits the publish name to a maximum of 50 characters.
|
||||
// If the combined length of the ID and the name exceeds 50 characters,
|
||||
// we will truncate the name to ensure the final result is within the limit.
|
||||
// The name should only contain alphanumeric characters and hyphens.
|
||||
Future<String> generatePublishName(String id, String name) async {
|
||||
final result = '${name.substring(0, min(49 - id.length, name.length))}-$id';
|
||||
return result.replaceAll(_regExp, '-');
|
||||
}
|
@ -1,17 +1,15 @@
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/plugins/document/application/document_share_bloc.dart';
|
||||
import 'package:appflowy/plugins/document/presentation/share/publish_name_generator.dart';
|
||||
import 'package:appflowy/workspace/presentation/home/toast.dart';
|
||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/uuid.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flowy_infra_ui/widget/rounded_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
final _regExp = RegExp(r'[^\w\-\.@:/]');
|
||||
|
||||
class PublishTab extends StatelessWidget {
|
||||
const PublishTab({super.key});
|
||||
|
||||
@ -40,8 +38,12 @@ class PublishTab extends StatelessWidget {
|
||||
)
|
||||
: _UnPublishWidget(
|
||||
onPublish: () async {
|
||||
final publishName = await _generatePublishName(context);
|
||||
final nameSpace = await _generateNameSpace();
|
||||
final id = context.read<DocumentShareBloc>().view.id;
|
||||
final publishName = await generatePublishName(
|
||||
id,
|
||||
state.viewName,
|
||||
);
|
||||
final nameSpace = await generateNameSpace();
|
||||
if (context.mounted) {
|
||||
context.read<DocumentShareBloc>().add(
|
||||
DocumentShareEvent.publish(nameSpace, publishName),
|
||||
@ -52,18 +54,6 @@ class PublishTab extends StatelessWidget {
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<String> _generateNameSpace() async {
|
||||
const workspaceName = '';
|
||||
final id = uuid().substring(0, 8);
|
||||
return '$workspaceName$id'.replaceAll(_regExp, '_');
|
||||
}
|
||||
|
||||
Future<String> _generatePublishName(BuildContext context) async {
|
||||
final publishName = context.read<DocumentShareBloc>().view.name;
|
||||
final id = uuid().substring(0, 8);
|
||||
return '$publishName$id'.replaceAll(_regExp, '');
|
||||
}
|
||||
}
|
||||
|
||||
class _PublishedWidget extends StatefulWidget {
|
||||
|
@ -1,20 +1,24 @@
|
||||
use crate::entities::ViewPB;
|
||||
use flowy_folder_pub::entities::PublishViewInfo;
|
||||
use regex::Regex;
|
||||
use tracing::trace;
|
||||
|
||||
fn replace_invalid_url_chars(input: &str) -> String {
|
||||
let re = Regex::new(r"[^\w-]").unwrap();
|
||||
|
||||
let replaced = re.replace_all(input, "_").to_string();
|
||||
if replaced.len() > 20 {
|
||||
replaced[..20].to_string()
|
||||
} else {
|
||||
replaced
|
||||
}
|
||||
let regex = Regex::new(r"[^\w-]").unwrap();
|
||||
regex.replace_all(input, "-").to_string()
|
||||
}
|
||||
|
||||
pub fn generate_publish_name(id: &str, name: &str) -> String {
|
||||
let id_len = id.len();
|
||||
let name = replace_invalid_url_chars(name);
|
||||
format!("{}-{}", name, id)
|
||||
let name_len = name.len();
|
||||
// The backend limits the publish name to a maximum of 50 characters.
|
||||
// If the combined length of the ID and the name exceeds 50 characters,
|
||||
// we will truncate the name to ensure the final result is within the limit.
|
||||
// The name should only contain alphanumeric characters and hyphens.
|
||||
let result = format!("{}-{}", &name[..std::cmp::min(49 - id_len, name_len)], id);
|
||||
trace!("generate_publish_name: {}", result);
|
||||
result
|
||||
}
|
||||
|
||||
pub fn view_pb_to_publish_view(view: &ViewPB) -> PublishViewInfo {
|
||||
|
Loading…
Reference in New Issue
Block a user