Compare commits

..

No commits in common. "a1701e216a5e977a1fca4820347edb5a4933bd13" and "0df5dc03fa936fc47ed64f907fffbd5bebd03925" have entirely different histories.

4 changed files with 7 additions and 69 deletions

View File

@ -41,12 +41,6 @@ class TranslationInputAndResourceContainer extends StatefulWidget {
class _TranslationInputAndResourceContainerState
extends State<TranslationInputAndResourceContainer> {
late Map<String, QuillController> _controllers;
/// Meme piege que dans `translation_input_container` : sans `focusNode` ni
/// `scrollController`, `QuillEditor.basic` en cree de neufs a chaque
/// construction et le champ perd le curseur des qu'un rebuild survient.
late Map<String, FocusNode> _focusNodes;
late Map<String, ScrollController> _editorScrollControllers;
int _selected = 0;
bool _isEnforcingLimit = false;
bool _isTranslating = false;
@ -56,14 +50,6 @@ class _TranslationInputAndResourceContainerState
void initState() {
super.initState();
_controllers = _buildControllers();
_focusNodes = {
for (final translation in widget.newValues)
translation.language!: FocusNode(),
};
_editorScrollControllers = {
for (final translation in widget.newValues)
translation.language!: ScrollController(),
};
}
static const _emptyDelta = [{'insert': '\n'}];
@ -186,12 +172,6 @@ class _TranslationInputAndResourceContainerState
for (final c in _controllers.values) {
c.dispose();
}
for (final node in _focusNodes.values) {
node.dispose();
}
for (final c in _editorScrollControllers.values) {
c.dispose();
}
super.dispose();
}
@ -416,8 +396,6 @@ class _TranslationInputAndResourceContainerState
),
child: QuillEditor.basic(
controller: controller,
focusNode: _focusNodes[lang],
scrollController: _editorScrollControllers[lang],
config: const QuillEditorConfig(
scrollable: true,
expands: false,

View File

@ -47,13 +47,6 @@ class TranslationInputContainer extends StatefulWidget {
class _TranslationInputContainerState extends State<TranslationInputContainer> {
late Map<String, QuillController> _controllers;
late Map<String, TextEditingController> _textControllers;
/// `QuillEditor.basic` fabrique un `FocusNode` et un `ScrollController` neufs
/// a chaque construction quand on ne lui en passe pas : le curseur sautait de
/// l'editeur des la premiere frappe, puisque chaque frappe reconstruit ce
/// widget (compteur de caracteres, pastilles du rail).
late Map<String, FocusNode> _focusNodes;
late Map<String, ScrollController> _editorScrollControllers;
int _selected = 0;
bool _isEnforcingLimit = false;
bool _isTranslating = false;
@ -64,14 +57,6 @@ class _TranslationInputContainerState extends State<TranslationInputContainer> {
super.initState();
_controllers = widget.isHTML ? _buildControllers() : {};
_textControllers = widget.isHTML ? {} : _buildTextControllers();
_focusNodes = {
for (final translation in widget.newValues)
translation.language!: FocusNode(),
};
_editorScrollControllers = {
for (final translation in widget.newValues)
translation.language!: ScrollController(),
};
}
Map<String, TextEditingController> _buildTextControllers() {
@ -222,12 +207,6 @@ class _TranslationInputContainerState extends State<TranslationInputContainer> {
for (final c in _textControllers.values) {
c.dispose();
}
for (final node in _focusNodes.values) {
node.dispose();
}
for (final c in _editorScrollControllers.values) {
c.dispose();
}
super.dispose();
}
@ -488,8 +467,6 @@ class _TranslationInputContainerState extends State<TranslationInputContainer> {
),
child: QuillEditor.basic(
controller: controller,
focusNode: _focusNodes[lang],
scrollController: _editorScrollControllers[lang],
config: const QuillEditorConfig(
scrollable: true,
expands: false,

View File

@ -492,9 +492,9 @@ class _ResourceBodyGridState extends State<ResourceBodyGrid> {
TextButton.icon(
icon: const Icon(Icons.download, size: 16),
label: Text(l.download, style: const TextStyle(fontSize: 12.5)),
onPressed: () async {
onPressed: () {
for (final resource in selected) {
await downloadResource(resource);
downloadResource(resource);
}
},
),

View File

@ -8,29 +8,12 @@ import 'resource_formatting.dart';
///
/// L'ancienne modale forçait `'${label}.json'` quel que soit le type : un PNG
/// arrivait en `mon-image.json` et ne s'ouvrait nulle part sans renommage.
///
/// Le fichier est d'abord récupéré en blob : l'attribut `download` d'un lien est
/// ignoré quand la cible est sur une autre origine (Firebase Storage ici), et le
/// navigateur se contentait d'ouvrir la ressource dans un onglet. Si la requête
/// échoue (CORS, réseau), on retombe sur l'ouverture dans un nouvel onglet.
Future<void> downloadResource(ResourceDTO resource) async {
void downloadResource(ResourceDTO resource) {
final url = resource.url;
if (url == null) return;
final fileName = downloadFileNameFor(resource);
try {
final request = await html.HttpRequest.request(url, responseType: 'blob');
final blob = request.response as html.Blob;
final objectUrl = html.Url.createObjectUrlFromBlob(blob);
html.AnchorElement(href: objectUrl)
..download = fileName
..click();
html.Url.revokeObjectUrl(objectUrl);
} catch (_) {
html.AnchorElement(href: url)
..download = fileName
..target = '_blank'
..click();
}
final anchor = html.AnchorElement(href: url)
..download = downloadFileNameFor(resource)
..target = '_blank';
anchor.click();
}