fix: the name is too long to publish

This commit is contained in:
Lucas.Xu 2024-06-28 10:24:03 +08:00
parent e51b0f90de
commit 2f9f2c1ba7
5 changed files with 75 additions and 32 deletions

View File

@ -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

View File

@ -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: '',
);
}

View File

@ -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, '-');
}

View File

@ -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 {

View File

@ -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 {