FEATURE: use native file picker in composer (#13552)
We want to remove completely our custom modal for uploading files in composer and directly trigger the system file picker.
This PR makes it happen. The fix is pretty simple since we already weren't using our custom modal on mobile. We just need to start using the same hidden <input type="file"> that we already use on mobile.
It seems to be pretty tricky to test opening a system modal so I haven't added new tests. We already have other tests for file uploading though. We directly trigger jquery-File-Upload plugin hooks in those tests - 3dda926cb2/app/assets/javascripts/discourse/tests/acceptance/composer-attachment-test.js (L89)
.
This commit is contained in:
parent
b63c9febe8
commit
a2e0da16a7
|
@ -831,10 +831,12 @@ export default Component.extend({
|
|||
});
|
||||
|
||||
if (this.site.mobileView) {
|
||||
$("#reply-control .mobile-file-upload").on("click.uploader", function () {
|
||||
// redirect the click on the hidden file input
|
||||
$("#mobile-uploader").click();
|
||||
});
|
||||
const uploadButton = document.getElementById("mobile-file-upload");
|
||||
uploadButton.addEventListener(
|
||||
"click",
|
||||
() => document.getElementById("file-uploader").click(),
|
||||
false
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
import {
|
||||
allowsAttachments,
|
||||
authorizedExtensions,
|
||||
uploadIcon,
|
||||
} from "discourse/lib/uploads";
|
||||
import Controller from "@ember/controller";
|
||||
import I18n from "I18n";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { equal } from "@ember/object/computed";
|
||||
|
||||
export default Controller.extend(ModalFunctionality, {
|
||||
imageUrl: null,
|
||||
local: equal("selection", "local"),
|
||||
remote: equal("selection", "remote"),
|
||||
selection: "local",
|
||||
|
||||
@discourseComputed()
|
||||
allowAdditionalFormats() {
|
||||
return allowsAttachments(this.currentUser.staff, this.siteSettings);
|
||||
},
|
||||
|
||||
@discourseComputed()
|
||||
uploadIcon() {
|
||||
return uploadIcon(this.currentUser.staff, this.siteSettings);
|
||||
},
|
||||
|
||||
@discourseComputed("allowAdditionalFormats")
|
||||
title(allowAdditionalFormats) {
|
||||
const suffix = allowAdditionalFormats ? "_with_attachments" : "";
|
||||
return `upload_selector.title${suffix}`;
|
||||
},
|
||||
|
||||
@discourseComputed("selection", "allowAdditionalFormats")
|
||||
tip(selection, allowAdditionalFormats) {
|
||||
const suffix = allowAdditionalFormats ? "_with_attachments" : "";
|
||||
return I18n.t(`upload_selector.${selection}_tip${suffix}`);
|
||||
},
|
||||
|
||||
@discourseComputed()
|
||||
supportedFormats() {
|
||||
const extensions = authorizedExtensions(
|
||||
this.currentUser.staff,
|
||||
this.siteSettings
|
||||
);
|
||||
|
||||
return `(${extensions})`;
|
||||
},
|
||||
|
||||
actions: {
|
||||
upload() {
|
||||
if (this.local) {
|
||||
$(".wmd-controls").fileupload("add", {
|
||||
fileInput: $("#filename-input"),
|
||||
});
|
||||
} else {
|
||||
const imageUrl = this.imageUrl || "";
|
||||
const toolbarEvent = this.toolbarEvent;
|
||||
|
||||
if (imageUrl.match(/\.(jpg|jpeg|png|gif|heic|heif|webp)$/)) {
|
||||
toolbarEvent.addText(`![](${imageUrl})`);
|
||||
} else {
|
||||
toolbarEvent.addText(imageUrl);
|
||||
}
|
||||
}
|
||||
this.send("closeModal");
|
||||
},
|
||||
},
|
||||
});
|
|
@ -137,11 +137,8 @@ const ApplicationRoute = DiscourseRoute.extend(OpenComposer, {
|
|||
showModal("not-activated", { title: "log_in" }).setProperties(props);
|
||||
},
|
||||
|
||||
showUploadSelector(toolbarEvent) {
|
||||
showModal("uploadSelector").setProperties({
|
||||
toolbarEvent,
|
||||
imageUrl: null,
|
||||
});
|
||||
showUploadSelector() {
|
||||
document.getElementById("file-uploader").click();
|
||||
},
|
||||
|
||||
showKeyboardShortcutsHelp() {
|
||||
|
|
|
@ -19,6 +19,4 @@
|
|||
disabled=disableTextarea
|
||||
outletArgs=(hash composer=composer editorType="composer")}}
|
||||
|
||||
{{#if site.mobileView}}
|
||||
<input type="file" id="mobile-uploader" multiple>
|
||||
{{/if}}
|
||||
<input type="file" id="file-uploader" multiple>
|
||||
|
|
|
@ -200,7 +200,7 @@
|
|||
{{plugin-outlet name="composer-mobile-buttons-bottom" connectorTagName="" args=(hash model=model)}}
|
||||
|
||||
{{#if allowUpload}}
|
||||
<a class="btn btn-default no-text mobile-file-upload {{if isUploading "hidden"}}" aria-label={{i18n "composer.upload_title"}}>
|
||||
<a id="mobile-file-upload" class="btn btn-default no-text mobile-file-upload {{if isUploading "hidden"}}" aria-label={{i18n "composer.upload_title"}}>
|
||||
{{d-icon uploadIcon}}
|
||||
</a>
|
||||
{{/if}}
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
{{#d-modal-body title=title class="upload-selector"}}
|
||||
<div class="radios">
|
||||
{{radio-button name="upload" id="local" value="local" selection=selection}}
|
||||
<label class="radio" for="local">{{i18n "upload_selector.from_my_computer"}}</label>
|
||||
{{#if local}}
|
||||
<div class="inputs">
|
||||
<input type="file" id="filename-input" multiple><br>
|
||||
<span class="description">{{tip}}</span>
|
||||
{{#if allowAdditionalFormats}}
|
||||
{{hidden-details label="upload_selector.supported_formats" details=supportedFormats}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="radios">
|
||||
{{radio-button name="upload" id="remote" value="remote" selection=selection}}
|
||||
<label class="radio" for="remote">{{i18n "upload_selector.from_the_web"}}</label>
|
||||
{{#if remote}}
|
||||
<div class="inputs">
|
||||
{{input value=imageUrl placeholder="http://example.com/image.png"}}
|
||||
<span class="description">{{tip}}</span>
|
||||
{{#if allowAdditionalFormats}}
|
||||
{{hidden-details label="upload_selector.supported_formats" details=supportedFormats}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="radios">
|
||||
<div class="inputs">
|
||||
<p class="hint">
|
||||
{{#if capabilities.canPasteImages}}
|
||||
{{i18n "upload_selector.hint"}}
|
||||
{{else}}
|
||||
{{i18n "upload_selector.hint_for_supported_browsers"}}
|
||||
{{/if}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{{/d-modal-body}}
|
||||
|
||||
<div class="modal-footer">
|
||||
{{d-button action=(action "upload") class="btn-primary" icon=uploadIcon label="upload"}}
|
||||
{{plugin-outlet name="upload-actions"}}
|
||||
{{d-modal-cancel close=(route-action "closeModal")}}
|
||||
</div>
|
|
@ -362,6 +362,10 @@
|
|||
#file-uploading {
|
||||
color: var(--primary-high);
|
||||
}
|
||||
|
||||
#file-uploader {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.autocomplete {
|
||||
|
|
|
@ -1,49 +1,3 @@
|
|||
.upload-selector {
|
||||
label {
|
||||
display: inline-block;
|
||||
padding-left: 10px;
|
||||
}
|
||||
&.modal-body {
|
||||
width: 460px;
|
||||
}
|
||||
.radios {
|
||||
min-height: 60px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
label {
|
||||
flex: 1 0 auto;
|
||||
margin-right: 1em;
|
||||
margin-top: 1px;
|
||||
}
|
||||
.inputs {
|
||||
width: 100%;
|
||||
input {
|
||||
width: 90%;
|
||||
margin: 0 0 5px 0;
|
||||
}
|
||||
input[type="file"] {
|
||||
font-size: $font-0;
|
||||
line-height: $line-height-medium;
|
||||
}
|
||||
.description,
|
||||
.hint {
|
||||
color: var(--primary-med-or-secondary-med);
|
||||
display: block;
|
||||
}
|
||||
.hint {
|
||||
font-style: italic;
|
||||
margin: 5px 0 0 0;
|
||||
}
|
||||
.label {
|
||||
margin: 0 0 5px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.radios:last-child {
|
||||
min-height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.uploaded-image-preview {
|
||||
height: 270px;
|
||||
width: 400px;
|
||||
|
|
|
@ -171,10 +171,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
#mobile-uploader {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.title-and-category,
|
||||
.user-selector {
|
||||
margin: 0;
|
||||
|
|
|
@ -1,37 +1,3 @@
|
|||
.upload-selector {
|
||||
input[type="text"] {
|
||||
width: calc(100% - 20px);
|
||||
}
|
||||
input[type="file"] {
|
||||
font-size: $font-0;
|
||||
line-height: $line-height-medium;
|
||||
}
|
||||
.description {
|
||||
color: var(--primary-medium);
|
||||
}
|
||||
.radios {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
&:first-of-type {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
input,
|
||||
label {
|
||||
min-height: 20px;
|
||||
line-height: $line-height-medium;
|
||||
margin: 0;
|
||||
}
|
||||
.radio {
|
||||
padding-left: 5px;
|
||||
}
|
||||
.inputs {
|
||||
margin-top: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.uploaded-image-preview {
|
||||
height: 150px;
|
||||
}
|
||||
|
|
|
@ -2236,21 +2236,10 @@ en:
|
|||
votes_released: "Vote was released"
|
||||
|
||||
upload_selector:
|
||||
title: "Add an image"
|
||||
title_with_attachments: "Add an image or a file"
|
||||
from_my_computer: "From my device"
|
||||
from_the_web: "From the web"
|
||||
remote_tip: "link to image"
|
||||
remote_tip_with_attachments: "link to image or file"
|
||||
local_tip: "select images from your device"
|
||||
local_tip_with_attachments: "select images or files from your device"
|
||||
hint: "(you can also drag & drop into the editor to upload)"
|
||||
hint_for_supported_browsers: "you can also drag and drop or paste images into the editor"
|
||||
uploading: "Uploading"
|
||||
processing: "Processing Upload"
|
||||
select_file: "Select File"
|
||||
default_image_alt_text: image
|
||||
supported_formats: "supported formats"
|
||||
|
||||
search:
|
||||
sort_by: "Sort by"
|
||||
|
|
|
@ -222,24 +222,6 @@ const path = require("path");
|
|||
return page.waitForSelector(".d-editor-preview p", { visible: true });
|
||||
});
|
||||
|
||||
await exec("open upload modal", () => {
|
||||
return page.click(".d-editor-button-bar .upload");
|
||||
});
|
||||
|
||||
await exec("upload modal is open", () => {
|
||||
return page.waitForSelector("#filename-input", { visible: true });
|
||||
});
|
||||
|
||||
await exec("upload modal closes", () => {
|
||||
let promise = page.click(".d-modal-cancel");
|
||||
|
||||
promise = promise.then(() => {
|
||||
return page.waitForSelector("#filename-input", { hidden: true });
|
||||
});
|
||||
|
||||
return promise;
|
||||
});
|
||||
|
||||
await exec("submit the topic", () => {
|
||||
return page.click(".submit-panel .create");
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue