mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: revamp mobile url editor (#4602)
* chore: revamp mobile url editor * chore: add i18n * chore: use shared url launcher * chore: translation bump * chore: add a toast notification after URL is copied to clipboard * chore: listen to onchanged * chore: improve text field editing experience * chore: disable quick action buttons if url cell data is empty * chore: apply suggestions from code review Co-authored-by: Mathias Mogensen <42929161+Xazin@users.noreply.github.com> * chore: provide the bloc and watch changes --------- Co-authored-by: Mathias Mogensen <42929161+Xazin@users.noreply.github.com>
This commit is contained in:
parent
48cac4c5ac
commit
25d4b4f718
@ -52,7 +52,7 @@ class _MobileBottomSheetRenameWidgetState
|
||||
height: 42.0,
|
||||
child: FlowyTextField(
|
||||
controller: controller,
|
||||
textInputAction: TextInputAction.done,
|
||||
keyboardType: TextInputType.text,
|
||||
onSubmitted: (text) => widget.onRename(text),
|
||||
),
|
||||
),
|
||||
|
@ -115,7 +115,7 @@ class _CopyURLAccessoryState extends State<_CopyURLAccessory>
|
||||
Widget build(BuildContext context) {
|
||||
if (widget.cellDataNotifier.value.isNotEmpty) {
|
||||
return FlowyTooltip(
|
||||
message: LocaleKeys.tooltip_urlCopyAccessory.tr(),
|
||||
message: LocaleKeys.grid_url_copy.tr(),
|
||||
preferBelow: false,
|
||||
child: _URLAccessoryIconContainer(
|
||||
child: FlowySvg(
|
||||
@ -161,7 +161,7 @@ class _VisitURLAccessoryState extends State<_VisitURLAccessory>
|
||||
Widget build(BuildContext context) {
|
||||
if (widget.cellDataNotifier.value.isNotEmpty) {
|
||||
return FlowyTooltip(
|
||||
message: LocaleKeys.tooltip_urlLaunchAccessory.tr(),
|
||||
message: LocaleKeys.grid_url_launch.tr(),
|
||||
preferBelow: false,
|
||||
child: _URLAccessoryIconContainer(
|
||||
child: FlowySvg(
|
||||
|
@ -1,5 +1,8 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/presentation/widgets/flowy_mobile_quick_action_button.dart';
|
||||
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||
import 'package:appflowy/plugins/database/application/cell/cell_controller.dart';
|
||||
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
|
||||
@ -8,8 +11,13 @@ import 'package:appflowy/plugins/database/widgets/row/accessory/cell_accessory.d
|
||||
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
|
||||
import 'package:appflowy/plugins/database/application/cell/bloc/url_cell_bloc.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/cell/editable_cell_builder.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../desktop_grid/desktop_grid_url_cell.dart';
|
||||
import '../desktop_row_detail/desktop_row_detail_url_cell.dart';
|
||||
@ -106,7 +114,8 @@ class _GridURLCellState extends GridEditableTextCell<EditableURLCell> {
|
||||
child: BlocListener<URLCellBloc, URLCellState>(
|
||||
listenWhen: (previous, current) => previous.content != current.content,
|
||||
listener: (context, state) {
|
||||
_textEditingController.text = state.content;
|
||||
_textEditingController.value =
|
||||
_textEditingController.value.copyWith(text: state.content);
|
||||
widget._cellDataNotifier.value = state.content;
|
||||
},
|
||||
child: widget.skin.build(
|
||||
@ -135,6 +144,74 @@ class _GridURLCellState extends GridEditableTextCell<EditableURLCell> {
|
||||
String? onCopy() => cellBloc.state.content;
|
||||
}
|
||||
|
||||
class MobileURLEditor extends StatelessWidget {
|
||||
const MobileURLEditor({
|
||||
super.key,
|
||||
required this.textEditingController,
|
||||
});
|
||||
|
||||
final TextEditingController textEditingController;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
const VSpace(4.0),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: FlowyTextField(
|
||||
controller: textEditingController,
|
||||
hintStyle: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium
|
||||
?.copyWith(color: Theme.of(context).hintColor),
|
||||
hintText: LocaleKeys.grid_url_textFieldHint.tr(),
|
||||
textStyle: Theme.of(context).textTheme.bodyMedium,
|
||||
keyboardType: TextInputType.url,
|
||||
hintTextConstraints: const BoxConstraints(maxHeight: 52),
|
||||
onChanged: (_) {
|
||||
if (textEditingController.value.composing.isCollapsed) {
|
||||
context
|
||||
.read<URLCellBloc>()
|
||||
.add(URLCellEvent.updateURL(textEditingController.text));
|
||||
}
|
||||
},
|
||||
onSubmitted: (text) =>
|
||||
context.read<URLCellBloc>().add(URLCellEvent.updateURL(text)),
|
||||
),
|
||||
),
|
||||
const VSpace(8.0),
|
||||
MobileQuickActionButton(
|
||||
enable: context.watch<URLCellBloc>().state.content.isNotEmpty,
|
||||
onTap: () {
|
||||
openUrlCellLink(textEditingController.text);
|
||||
context.pop();
|
||||
},
|
||||
icon: FlowySvgs.url_s,
|
||||
text: LocaleKeys.grid_url_launch.tr(),
|
||||
),
|
||||
const Divider(height: 8.5, thickness: 0.5),
|
||||
MobileQuickActionButton(
|
||||
enable: context.watch<URLCellBloc>().state.content.isNotEmpty,
|
||||
onTap: () {
|
||||
Clipboard.setData(
|
||||
ClipboardData(text: textEditingController.text),
|
||||
);
|
||||
Fluttertoast.showToast(
|
||||
msg: LocaleKeys.grid_url_copiedNotification.tr(),
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
);
|
||||
context.pop();
|
||||
},
|
||||
icon: FlowySvgs.copy_s,
|
||||
text: LocaleKeys.grid_url_copy.tr(),
|
||||
),
|
||||
const Divider(height: 8.5, thickness: 0.5),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void openUrlCellLink(String content) {
|
||||
if (RegExp(regexUrl).hasMatch(content)) {
|
||||
const linkPrefix = [
|
||||
|
@ -1,14 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
|
||||
import 'package:appflowy/plugins/database/application/cell/bloc/url_cell_bloc.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/row/accessory/cell_accessory.dart';
|
||||
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../editable_cell_skeleton/url.dart';
|
||||
|
||||
@ -25,53 +20,9 @@ class MobileGridURLCellSkin extends IEditableURLCellSkin {
|
||||
return BlocSelector<URLCellBloc, URLCellState, String>(
|
||||
selector: (state) => state.content,
|
||||
builder: (context, content) {
|
||||
if (content.isEmpty) {
|
||||
return TextField(
|
||||
focusNode: focusNode,
|
||||
keyboardType: TextInputType.url,
|
||||
decoration: const InputDecoration(
|
||||
enabledBorder: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
horizontal: 14,
|
||||
vertical: 12,
|
||||
),
|
||||
isCollapsed: true,
|
||||
),
|
||||
onTapOutside: (event) =>
|
||||
FocusManager.instance.primaryFocus?.unfocus(),
|
||||
onSubmitted: (value) => bloc.add(URLCellEvent.updateURL(value)),
|
||||
);
|
||||
}
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
if (content.isEmpty) {
|
||||
return;
|
||||
}
|
||||
final shouldAddScheme = !['http', 'https']
|
||||
.any((pattern) => content.startsWith(pattern));
|
||||
final url = shouldAddScheme ? 'http://$content' : content;
|
||||
afLaunchUrlString(url);
|
||||
},
|
||||
onLongPress: () => showMobileBottomSheet(
|
||||
context,
|
||||
title: LocaleKeys.board_mobile_editURL.tr(),
|
||||
showHeader: true,
|
||||
showCloseButton: true,
|
||||
builder: (_) {
|
||||
final controller = TextEditingController(text: content);
|
||||
return TextField(
|
||||
controller: controller,
|
||||
autofocus: true,
|
||||
keyboardType: TextInputType.url,
|
||||
onEditingComplete: () {
|
||||
bloc.add(URLCellEvent.updateURL(controller.text));
|
||||
context.pop();
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
onTap: () => _showURLEditor(context, bloc, textEditingController),
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: Container(
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
||||
@ -92,6 +43,23 @@ class MobileGridURLCellSkin extends IEditableURLCellSkin {
|
||||
);
|
||||
}
|
||||
|
||||
void _showURLEditor(
|
||||
BuildContext context,
|
||||
URLCellBloc bloc,
|
||||
TextEditingController textEditingController,
|
||||
) {
|
||||
showMobileBottomSheet(
|
||||
context,
|
||||
showDragHandle: true,
|
||||
builder: (context) => BlocProvider.value(
|
||||
value: bloc,
|
||||
child: MobileURLEditor(
|
||||
textEditingController: textEditingController,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<GridCellAccessoryBuilder<State<StatefulWidget>>> accessoryBuilder(
|
||||
GridCellAccessoryBuildContext context,
|
||||
|
@ -1,6 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
|
||||
import 'package:appflowy/plugins/database/application/cell/bloc/url_cell_bloc.dart';
|
||||
@ -8,7 +7,6 @@ import 'package:appflowy/plugins/database/widgets/row/accessory/cell_accessory.d
|
||||
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../editable_cell_skeleton/url.dart';
|
||||
|
||||
@ -27,17 +25,18 @@ class MobileRowDetailURLCellSkin extends IEditableURLCellSkin {
|
||||
builder: (context, content) {
|
||||
return InkWell(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(14)),
|
||||
onTap: () {
|
||||
if (content.isEmpty) {
|
||||
_showURLEditor(context, bloc, content);
|
||||
return;
|
||||
}
|
||||
final shouldAddScheme = !['http', 'https']
|
||||
.any((pattern) => content.startsWith(pattern));
|
||||
final url = shouldAddScheme ? 'http://$content' : content;
|
||||
afLaunchUrlString(url);
|
||||
},
|
||||
onLongPress: () => _showURLEditor(context, bloc, content),
|
||||
onTap: () => showMobileBottomSheet(
|
||||
context,
|
||||
showDragHandle: true,
|
||||
builder: (_) {
|
||||
return BlocProvider.value(
|
||||
value: bloc,
|
||||
child: MobileURLEditor(
|
||||
textEditingController: textEditingController,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
child: Container(
|
||||
constraints: const BoxConstraints(
|
||||
minHeight: 48,
|
||||
@ -77,25 +76,4 @@ class MobileRowDetailURLCellSkin extends IEditableURLCellSkin {
|
||||
URLCellDataNotifier cellDataNotifier,
|
||||
) =>
|
||||
const [];
|
||||
|
||||
void _showURLEditor(BuildContext context, URLCellBloc bloc, String content) {
|
||||
final controller = TextEditingController(text: content);
|
||||
showMobileBottomSheet(
|
||||
context,
|
||||
title: LocaleKeys.board_mobile_editURL.tr(),
|
||||
showHeader: true,
|
||||
showCloseButton: true,
|
||||
builder: (_) {
|
||||
return TextField(
|
||||
controller: controller,
|
||||
autofocus: true,
|
||||
keyboardType: TextInputType.url,
|
||||
onEditingComplete: () {
|
||||
bloc.add(URLCellEvent.updateURL(controller.text));
|
||||
context.pop();
|
||||
},
|
||||
);
|
||||
},
|
||||
).then((_) => controller.dispose());
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ class FlowyTextField extends StatefulWidget {
|
||||
final TextStyle? hintStyle;
|
||||
final InputDecoration? decoration;
|
||||
final TextAlignVertical? textAlignVertical;
|
||||
final TextInputAction? textInputAction;
|
||||
final TextInputType? keyboardType;
|
||||
final List<TextInputFormatter>? inputFormatters;
|
||||
|
||||
const FlowyTextField({
|
||||
@ -60,7 +60,7 @@ class FlowyTextField extends StatefulWidget {
|
||||
this.hintStyle,
|
||||
this.decoration,
|
||||
this.textAlignVertical,
|
||||
this.textInputAction,
|
||||
this.keyboardType = TextInputType.multiline,
|
||||
this.inputFormatters,
|
||||
});
|
||||
|
||||
@ -145,7 +145,6 @@ class FlowyTextFieldState extends State<FlowyTextField> {
|
||||
_onChanged(text);
|
||||
}
|
||||
},
|
||||
textInputAction: widget.textInputAction,
|
||||
onSubmitted: (text) => _onSubmitted(text),
|
||||
onEditingComplete: widget.onEditingComplete,
|
||||
minLines: 1,
|
||||
@ -154,7 +153,7 @@ class FlowyTextFieldState extends State<FlowyTextField> {
|
||||
maxLengthEnforcement: MaxLengthEnforcement.truncateAfterCompositionEnds,
|
||||
style: widget.textStyle ?? Theme.of(context).textTheme.bodySmall,
|
||||
textAlignVertical: widget.textAlignVertical ?? TextAlignVertical.center,
|
||||
keyboardType: TextInputType.multiline,
|
||||
keyboardType: widget.keyboardType,
|
||||
inputFormatters: widget.inputFormatters,
|
||||
decoration: widget.decoration ??
|
||||
InputDecoration(
|
||||
|
@ -178,9 +178,7 @@
|
||||
"dragRow": "اضغط مطولاً لإعادة ترتيب الصف",
|
||||
"viewDataBase": "عرض قاعدة البيانات",
|
||||
"referencePage": "تمت الإشارة إلى هذا {name}",
|
||||
"addBlockBelow": "إضافة كتلة أدناه",
|
||||
"urlLaunchAccessory": "فتح في المتصفح",
|
||||
"urlCopyAccessory": "إنسخ الرابط"
|
||||
"addBlockBelow": "إضافة كتلة أدناه"
|
||||
},
|
||||
"sideBar": {
|
||||
"closeSidebar": "إغلاق الشريط الجانبي",
|
||||
@ -625,6 +623,10 @@
|
||||
"hideComplete": "إخفاء المهام المكتملة",
|
||||
"showComplete": "إظهار كافة المهام"
|
||||
},
|
||||
"url": {
|
||||
"launch": "فتح في المتصفح",
|
||||
"copy": "إنسخ الرابط"
|
||||
},
|
||||
"menuName": "شبكة",
|
||||
"referencedGridPrefix": "نظرا ل"
|
||||
},
|
||||
|
@ -176,9 +176,7 @@
|
||||
"dragRow": "Premeu llargament per reordenar la fila",
|
||||
"viewDataBase": "Veure base de dades",
|
||||
"referencePage": "Es fa referència a aquest {nom}",
|
||||
"addBlockBelow": "Afegeix un bloc a continuació",
|
||||
"urlLaunchAccessory": "Oberta al navegador",
|
||||
"urlCopyAccessory": "Copia l'URL"
|
||||
"addBlockBelow": "Afegeix un bloc a continuació"
|
||||
},
|
||||
"sideBar": {
|
||||
"closeSidebar": "Close sidebar",
|
||||
@ -573,6 +571,10 @@
|
||||
"addNew": "Afegeix un element",
|
||||
"submitNewTask": "Crear"
|
||||
},
|
||||
"url": {
|
||||
"launch": "Oberta al navegador",
|
||||
"copy": "Copia l'URL"
|
||||
},
|
||||
"menuName": "Quadrícula",
|
||||
"referencedGridPrefix": "Vista de"
|
||||
},
|
||||
|
@ -177,9 +177,7 @@
|
||||
"dragRow": "Gedrückt halten, um die Zeile neu anzuordnen",
|
||||
"viewDataBase": "Datenbank ansehen",
|
||||
"referencePage": "Auf diesen {Name} wird verwiesen",
|
||||
"addBlockBelow": "Einen Block unten hinzufügen",
|
||||
"urlLaunchAccessory": "Im Browser öffnen",
|
||||
"urlCopyAccessory": "Webadresse kopieren."
|
||||
"addBlockBelow": "Einen Block unten hinzufügen"
|
||||
},
|
||||
"sideBar": {
|
||||
"closeSidebar": "Seitenleiste schließen",
|
||||
@ -639,6 +637,10 @@
|
||||
"hideComplete": "Blende abgeschlossene Aufgaben aus",
|
||||
"showComplete": "Zeige alle Aufgaben"
|
||||
},
|
||||
"url": {
|
||||
"launch": "Im Browser öffnen",
|
||||
"copy": "Webadresse kopieren"
|
||||
},
|
||||
"menuName": "Raster",
|
||||
"referencedGridPrefix": "Sicht von"
|
||||
},
|
||||
|
@ -198,9 +198,7 @@
|
||||
"dragRow": "Long press to reorder the row",
|
||||
"viewDataBase": "View database",
|
||||
"referencePage": "This {name} is referenced",
|
||||
"addBlockBelow": "Add a block below",
|
||||
"urlLaunchAccessory": "Open in browser",
|
||||
"urlCopyAccessory": "Copy URL"
|
||||
"addBlockBelow": "Add a block below"
|
||||
},
|
||||
"sideBar": {
|
||||
"closeSidebar": "Close side bar",
|
||||
@ -732,6 +730,12 @@
|
||||
"hideComplete": "Hide completed tasks",
|
||||
"showComplete": "Show all tasks"
|
||||
},
|
||||
"url": {
|
||||
"launch": "Open link in browser",
|
||||
"copy": "Copy link to clipboard",
|
||||
"textFieldHint": "Enter a URL",
|
||||
"copiedNotification": "Copied to clipboard!"
|
||||
},
|
||||
"relation": {
|
||||
"relatedDatabasePlaceLabel": "Related Database",
|
||||
"relatedDatabasePlaceholder": "None",
|
||||
|
@ -180,9 +180,7 @@
|
||||
"dragRow": "Pulsación larga para reordenar la fila",
|
||||
"viewDataBase": "Ver base de datos",
|
||||
"referencePage": "Se hace referencia a este {nombre}",
|
||||
"addBlockBelow": "Añadir un bloque a continuación",
|
||||
"urlLaunchAccessory": "Abrir en el navegador",
|
||||
"urlCopyAccessory": "Copiar URL"
|
||||
"addBlockBelow": "Añadir un bloque a continuación"
|
||||
},
|
||||
"sideBar": {
|
||||
"closeSidebar": "Cerrar panel lateral",
|
||||
@ -627,6 +625,10 @@
|
||||
"hideComplete": "Ocultar tareas completadas",
|
||||
"showComplete": "Mostrar todas las tareas"
|
||||
},
|
||||
"url": {
|
||||
"launch": "Abrir en el navegador",
|
||||
"copy": "Copiar URL"
|
||||
},
|
||||
"menuName": "Cuadrícula",
|
||||
"referencedGridPrefix": "Vista de"
|
||||
},
|
||||
|
@ -182,9 +182,7 @@
|
||||
"dragRow": "Appuyez longuement pour réorganiser la ligne",
|
||||
"viewDataBase": "Voir la base de données",
|
||||
"referencePage": "Ce {nom} est référencé",
|
||||
"addBlockBelow": "Ajouter un bloc ci-dessous",
|
||||
"urlLaunchAccessory": "Ouvrir dans le navigateur",
|
||||
"urlCopyAccessory": "Copier l'URL"
|
||||
"addBlockBelow": "Ajouter un bloc ci-dessous"
|
||||
},
|
||||
"sideBar": {
|
||||
"closeSidebar": "Fermer le menu latéral",
|
||||
@ -659,6 +657,10 @@
|
||||
"hideComplete": "Cacher les tâches terminées",
|
||||
"showComplete": "Afficher toutes les tâches"
|
||||
},
|
||||
"url": {
|
||||
"launch": "Ouvrir dans le navigateur",
|
||||
"copy": "Copier l'URL"
|
||||
},
|
||||
"menuName": "Grille",
|
||||
"referencedGridPrefix": "Vue",
|
||||
"calculate": "Calculer",
|
||||
@ -1264,4 +1266,4 @@
|
||||
"userIcon": "Icône utilisateur"
|
||||
},
|
||||
"noLogFiles": "Il n'y a pas de log"
|
||||
}
|
||||
}
|
@ -187,9 +187,7 @@
|
||||
"dragRow": "Appuyez longuement pour réorganiser la ligne",
|
||||
"viewDataBase": "Voir la base de données",
|
||||
"referencePage": "Ce {nom} est référencé",
|
||||
"addBlockBelow": "Ajouter un bloc ci-dessous",
|
||||
"urlLaunchAccessory": "Ouvrir dans le navigateur",
|
||||
"urlCopyAccessory": "Copier l'URL"
|
||||
"addBlockBelow": "Ajouter un bloc ci-dessous"
|
||||
},
|
||||
"sideBar": {
|
||||
"closeSidebar": "Fermer le menu latéral",
|
||||
@ -703,6 +701,10 @@
|
||||
"hideComplete": "Cacher les tâches terminées",
|
||||
"showComplete": "Afficher toutes les tâches"
|
||||
},
|
||||
"url": {
|
||||
"launch": "Ouvrir dans le navigateur",
|
||||
"copy": "Copier l'URL"
|
||||
},
|
||||
"relation": {
|
||||
"inRelatedDatabase": "Dans",
|
||||
"emptySearchResult": "Aucun enregistrement trouvé"
|
||||
|
@ -183,9 +183,7 @@
|
||||
"dragRow": "Premere a lungo per riordinare la riga",
|
||||
"viewDataBase": "Visualizza banca dati",
|
||||
"referencePage": "Questo {nome} è referenziato",
|
||||
"addBlockBelow": "Aggiungi un blocco qui sotto",
|
||||
"urlLaunchAccessory": "Apri nel browser",
|
||||
"urlCopyAccessory": "Copia l'URL"
|
||||
"addBlockBelow": "Aggiungi un blocco qui sotto"
|
||||
},
|
||||
"sideBar": {
|
||||
"closeSidebar": "Close sidebar",
|
||||
@ -665,6 +663,10 @@
|
||||
"hideComplete": "Nascondi le attività completate",
|
||||
"showComplete": "Mostra tutte le attività"
|
||||
},
|
||||
"url": {
|
||||
"launch": "Apri nel browser",
|
||||
"copy": "Copia l'URL"
|
||||
},
|
||||
"menuName": "Griglia",
|
||||
"referencedGridPrefix": "Vista di",
|
||||
"calculate": "Calcolare",
|
||||
|
@ -180,9 +180,7 @@
|
||||
"dragRow": "Pressione e segure para reordenar a linha",
|
||||
"viewDataBase": "Visualizar banco de dados",
|
||||
"referencePage": "Esta {name} é uma referência",
|
||||
"addBlockBelow": "Adicione um bloco abaixo",
|
||||
"urlLaunchAccessory": "Abrir com o navegador",
|
||||
"urlCopyAccessory": "Copiar URL"
|
||||
"addBlockBelow": "Adicione um bloco abaixo"
|
||||
},
|
||||
"sideBar": {
|
||||
"closeSidebar": "Fechar barra lateral",
|
||||
@ -648,6 +646,10 @@
|
||||
"hideComplete": "Ocultar tarefas concluídas",
|
||||
"showComplete": "Mostrar todas as tarefas"
|
||||
},
|
||||
"url": {
|
||||
"launch": "Abrir com o navegador",
|
||||
"copy": "Copiar URL"
|
||||
},
|
||||
"menuName": "Grade",
|
||||
"referencedGridPrefix": "Vista de"
|
||||
},
|
||||
|
@ -187,9 +187,7 @@
|
||||
"dragRow": "Перетащите для изменения порядка строк",
|
||||
"viewDataBase": "Просмотр базы данных",
|
||||
"referencePage": "Ссылки на {name}",
|
||||
"addBlockBelow": "Добавьте блок ниже",
|
||||
"urlLaunchAccessory": "Открыть в браузере",
|
||||
"urlCopyAccessory": "Скопировать URL"
|
||||
"addBlockBelow": "Добавьте блок ниже"
|
||||
},
|
||||
"sideBar": {
|
||||
"closeSidebar": "Закрыть боковое меню",
|
||||
@ -689,6 +687,10 @@
|
||||
"hideComplete": "Скрыть выполненные задачи",
|
||||
"showComplete": "Показать все задачи"
|
||||
},
|
||||
"url": {
|
||||
"launch": "Открыть в браузере",
|
||||
"copy": "Скопировать URL"
|
||||
},
|
||||
"relation": {
|
||||
"relatedDatabasePlaceLabel": "Связанная база данных",
|
||||
"relatedDatabasePlaceholder": "Пусто",
|
||||
|
@ -177,9 +177,7 @@
|
||||
"dragRow": "กดค้างเพื่อเรียงลำดับแถวใหม่",
|
||||
"viewDataBase": "ดูฐานข้อมูล",
|
||||
"referencePage": "{name} ถูกอ้างอิงถึง",
|
||||
"addBlockBelow": "เพิ่มบล็อกด้านล่าง",
|
||||
"urlLaunchAccessory": "เปิดในเบราว์เซอร์",
|
||||
"urlCopyAccessory": "คัดลอก URL"
|
||||
"addBlockBelow": "เพิ่มบล็อกด้านล่าง"
|
||||
},
|
||||
"sideBar": {
|
||||
"closeSidebar": "ปิดแถบด้านข้าง",
|
||||
@ -557,7 +555,7 @@
|
||||
"showHiddenFields": {
|
||||
"one": "แสดงฟิลด์ที่ซ่อนอยู่ {count} ฟิลด์",
|
||||
"many": "แสดงฟิลด์ที่ซ่อนอยู่ {count} ฟิลด์",
|
||||
"other": "แสดงฟิลด์ที่ซ่อนอยู่ {count} ฟิลด์"
|
||||
"other": "แสดงฟิลด์ที่ซ่อนอยู่ {count} ฟิลด์"
|
||||
},
|
||||
"hideHiddenFields": {
|
||||
"one": "ซ่อนฟิลด์ที่ซ่อนอยู่ {count} ฟิลด์",
|
||||
@ -614,6 +612,10 @@
|
||||
"hideComplete": "ซ่อนงานเสร็จ",
|
||||
"showComplete": "แสดงงานทั้งหมด"
|
||||
},
|
||||
"url": {
|
||||
"launch": "เปิดในเบราว์เซอร์",
|
||||
"copy": "คัดลอก URL"
|
||||
},
|
||||
"menuName": "ตาราง",
|
||||
"referencedGridPrefix": "มุมมองของ"
|
||||
},
|
||||
@ -630,11 +632,11 @@
|
||||
},
|
||||
"grid": {
|
||||
"selectAGridToLinkTo": "เลือกตารางเพื่อเชื่อมโยง",
|
||||
"createANewGrid": "สร้างตารางใหม่"
|
||||
"createANewGrid": "สร้างตารางใหม่"
|
||||
},
|
||||
"calendar": {
|
||||
"selectACalendarToLinkTo": "เลือกปฏิทินเพื่อเชื่อมโยง",
|
||||
"createANewCalendar": "สร้างปฏิทินใหม่"
|
||||
"createANewCalendar": "สร้างปฏิทินใหม่"
|
||||
},
|
||||
"document": {
|
||||
"selectADocumentToLinkTo": "เลือกเอกสารเพื่อเชื่อมโยง"
|
||||
@ -764,7 +766,7 @@
|
||||
},
|
||||
"stability_ai": {
|
||||
"label": "สร้างรูปภาพจาก Stability AI",
|
||||
"placeholder": "โปรดระบุคำขอใช้ Stability AI สร้างรูปภาพ"
|
||||
"placeholder": "โปรดระบุคำขอใช้ Stability AI สร้างรูปภาพ"
|
||||
},
|
||||
"support": "ขนาดรูปภาพจำกัดอยู่ที่ 5MB รูปแบบที่รองรับ: JPEG, PNG, GIF, SVG",
|
||||
"error": {
|
||||
|
@ -175,8 +175,7 @@
|
||||
"openMenu": "Bấm để mở menu",
|
||||
"dragRow": "Nhấn và giữ để sắp xếp lại hàng",
|
||||
"viewDataBase": "Xem cơ sở dữ liệu",
|
||||
"referencePage": "{name} này được tham chiếu",
|
||||
"urlCopyAccessory": "Sao chép URL"
|
||||
"referencePage": "{name} này được tham chiếu"
|
||||
},
|
||||
"sideBar": {
|
||||
"closeSidebar": "Đóng thanh bên",
|
||||
@ -612,6 +611,9 @@
|
||||
"searchOrCreateOption": "Tìm kiếm hoặc tạo một tùy chọn...",
|
||||
"tagName": "Tên thẻ"
|
||||
},
|
||||
"url": {
|
||||
"copy": "Sao chép URL"
|
||||
},
|
||||
"menuName": "Lưới"
|
||||
},
|
||||
"document": {
|
||||
|
@ -187,9 +187,7 @@
|
||||
"dragRow": "长按重新排序该行",
|
||||
"viewDataBase": "查看数据库",
|
||||
"referencePage": "这个 {name} 已被引用",
|
||||
"addBlockBelow": "在下面添加一个块",
|
||||
"urlLaunchAccessory": "在浏览器中打开",
|
||||
"urlCopyAccessory": "复制链接"
|
||||
"addBlockBelow": "在下面添加一个块"
|
||||
},
|
||||
"sideBar": {
|
||||
"closeSidebar": "关闭侧边栏",
|
||||
@ -691,6 +689,10 @@
|
||||
"hideComplete": "隐藏已完成的任务",
|
||||
"showComplete": "显示所有任务"
|
||||
},
|
||||
"url": {
|
||||
"launch": "在浏览器中打开",
|
||||
"copy": "复制链接"
|
||||
},
|
||||
"relation": {
|
||||
"emptySearchResult": "无结果"
|
||||
},
|
||||
|
@ -181,9 +181,7 @@
|
||||
"dragRow": "長按以重新排序列",
|
||||
"viewDataBase": "檢視資料庫",
|
||||
"referencePage": "這個 {name} 已被引用",
|
||||
"addBlockBelow": "在下方新增一個區塊",
|
||||
"urlLaunchAccessory": "在瀏覽器中開啟",
|
||||
"urlCopyAccessory": "複製網址"
|
||||
"addBlockBelow": "在下方新增一個區塊"
|
||||
},
|
||||
"sideBar": {
|
||||
"closeSidebar": "關閉側欄",
|
||||
@ -650,6 +648,10 @@
|
||||
"hideComplete": "隱藏已完成任務",
|
||||
"showComplete": "顯示所有任務"
|
||||
},
|
||||
"url": {
|
||||
"launch": "在瀏覽器中開啟",
|
||||
"copy": "複製網址"
|
||||
},
|
||||
"menuName": "網格",
|
||||
"referencedGridPrefix": "檢視",
|
||||
"calculate": "計算",
|
||||
|
Loading…
Reference in New Issue
Block a user