start adding media uploads
This commit is contained in:
parent
66a803b170
commit
cd376c5a18
23
routes/_actions/media.js
Normal file
23
routes/_actions/media.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { store } from '../_store/store'
|
||||
import { uploadMedia } from '../_api/media'
|
||||
import { toast } from '../_utils/toast'
|
||||
|
||||
export async function doMediaUpload(file) {
|
||||
let instanceName = store.get('currentInstance')
|
||||
let accessToken = store.get('accessToken')
|
||||
store.set({uploadingMedia: true})
|
||||
try {
|
||||
let response = await uploadMedia(instanceName, accessToken, file)
|
||||
let mediaToUpload = store.get('mediaToUpload') || []
|
||||
mediaToUpload.push({
|
||||
data: response,
|
||||
file: file
|
||||
})
|
||||
store.set({ mediaToUpload })
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
toast.say('Failed to upload media: ' + (e.message || ''))
|
||||
} finally {
|
||||
store.set({uploadingMedia: false})
|
||||
}
|
||||
}
|
9
routes/_api/media.js
Normal file
9
routes/_api/media.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { auth, basename } from './utils'
|
||||
import { postWithTimeout } from '../_utils/ajax'
|
||||
|
||||
export async function uploadMedia (instanceName, accessToken, file) {
|
||||
let formData = new FormData()
|
||||
formData.append('file', file)
|
||||
let url = `${basename(instanceName)}/api/v1/media`
|
||||
return postWithTimeout(url, formData, auth(accessToken))
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
<ComposeLengthGauge />
|
||||
<ComposeToolbar />
|
||||
<ComposeLengthIndicator />
|
||||
<ComposeMedia />
|
||||
<ComposeButton />
|
||||
</div>
|
||||
<style>
|
||||
|
@ -17,6 +18,7 @@
|
|||
"avatar input input input"
|
||||
"avatar gauge gauge gauge"
|
||||
"avatar toolbar toolbar length"
|
||||
"avatar media media media"
|
||||
"avatar button button button";
|
||||
grid-template-columns: min-content minmax(0, max-content) 1fr 1fr;
|
||||
border-bottom: 1px solid var(--main-border);
|
||||
|
@ -39,6 +41,7 @@
|
|||
import ComposeAuthor from './ComposeAuthor.html'
|
||||
import ComposeInput from './ComposeInput.html'
|
||||
import ComposeButton from './ComposeButton.html'
|
||||
import ComposeMedia from './ComposeMedia.html'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -47,7 +50,8 @@
|
|||
ComposeLengthGauge,
|
||||
ComposeLengthIndicator,
|
||||
ComposeInput,
|
||||
ComposeButton
|
||||
ComposeButton,
|
||||
ComposeMedia
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
94
routes/_components/compose/ComposeMedia.html
Normal file
94
routes/_components/compose/ComposeMedia.html
Normal file
|
@ -0,0 +1,94 @@
|
|||
{{#if $mediaToUpload && $mediaToUpload.length}}
|
||||
<div class="compose-media-container" style="grid-template-columns: repeat({{$mediaToUpload.length}}, 1fr);">
|
||||
{{#each $mediaToUpload as media}}
|
||||
<div class="compose-media">
|
||||
<img src="{{media.data.preview_url}}" alt="{{media.file.name}}"/>
|
||||
<div class="compose-media-delete">
|
||||
<button class="compose-media-delete-button" data-a11y-dialog-hide aria-label="Delete {{media.file.name}}">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="compose-media-alt">
|
||||
<input type="text"
|
||||
placeholder="Description"
|
||||
aria-label="Describe {{media.file.name}} for the visually impaired">
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
<style>
|
||||
.compose-media-container {
|
||||
grid-area: media;
|
||||
display: grid;
|
||||
grid-column-gap: 5px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 10px;
|
||||
background: var(--form-bg);
|
||||
padding: 5px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.compose-media {
|
||||
height: 200px;
|
||||
overflow: hidden;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
display: flex;
|
||||
background: var(--main-bg);
|
||||
}
|
||||
.compose-media img {
|
||||
object-fit: contain;
|
||||
object-position: center center;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.compose-media-alt {
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.compose-media-alt input {
|
||||
width: 100%;
|
||||
font-size: 1.2em;
|
||||
background: var(--alt-input-bg);
|
||||
}
|
||||
.compose-media-alt input:focus {
|
||||
background: var(--main-bg);
|
||||
}
|
||||
.compose-media-delete {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin: 2px;
|
||||
}
|
||||
.compose-media-delete-button {
|
||||
padding: 0 0 7px;
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
.compose-media-delete-button:hover {
|
||||
background: var(--toast-border);
|
||||
}
|
||||
.compose-media-delete-button span {
|
||||
padding: 0 10px 7px;
|
||||
font-size: 32px;
|
||||
color: var(--button-text);
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import { store } from '../../_store/store'
|
||||
|
||||
export default {
|
||||
store: () => store
|
||||
}
|
||||
</script>
|
|
@ -29,6 +29,7 @@
|
|||
import { store } from '../../_store/store'
|
||||
import { updateCustomEmojiForInstance } from '../../_actions/emoji'
|
||||
import { importDialogs } from '../../_utils/asyncModules'
|
||||
import { doMediaUpload } from '../../_actions/media'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -46,6 +47,7 @@
|
|||
},
|
||||
onFileChange(e) {
|
||||
let file = e.target.files[0]
|
||||
doMediaUpload(file)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,11 +24,14 @@ async function _post (url, body, headers, timeout) {
|
|||
method: 'POST'
|
||||
}
|
||||
if (body) {
|
||||
opts.headers = Object.assign(headers, {
|
||||
let isFormData = body instanceof FormData
|
||||
opts.headers = Object.assign(headers, isFormData ? {
|
||||
'Accept': 'application/json'
|
||||
} : {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
})
|
||||
opts.body = JSON.stringify(body)
|
||||
opts.body = isFormData ? body : JSON.stringify(body)
|
||||
} else {
|
||||
opts.headers = Object.assign(headers, {
|
||||
'Accept': 'application/json'
|
||||
|
|
|
@ -69,4 +69,5 @@
|
|||
--status-direct-background: darken($body-bg-color, 5%);
|
||||
--main-theme-color: $main-theme-color;
|
||||
--warning-color: #e01f19;
|
||||
--alt-input-bg: rgba($main-bg-color, 0.7);
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
|
||||
<style>
|
||||
/* auto-generated w/ build-sass.js */
|
||||
body{--button-primary-bg:#6081e6;--button-primary-text:#fff;--button-primary-border:#132c76;--button-primary-bg-active:#456ce2;--button-primary-bg-hover:#6988e7;--button-bg:#e6e6e6;--button-text:#333;--button-border:#a7a7a7;--button-bg-active:#bfbfbf;--button-bg-hover:#f2f2f2;--input-border:#dadada;--anchor-text:#4169e1;--main-bg:#fff;--body-bg:#e8edfb;--body-text-color:#333;--main-border:#dadada;--svg-fill:#4169e1;--form-bg:#f7f7f7;--form-border:#c1c1c1;--nav-bg:#4169e1;--nav-border:#214cce;--nav-a-border:#4169e1;--nav-a-selected-border:#fff;--nav-a-selected-bg:#6d8ce8;--nav-svg-fill:#fff;--nav-text-color:#fff;--nav-a-selected-border-hover:#fff;--nav-a-selected-bg-hover:#839deb;--nav-a-bg-hover:#577ae4;--nav-a-border-hover:#4169e1;--nav-svg-fill-hover:#fff;--nav-text-color-hover:#fff;--action-button-fill-color:#90a8ee;--action-button-fill-color-hover:#a2b6f0;--action-button-fill-color-active:#577ae4;--action-button-fill-color-pressed:#2351dc;--action-button-fill-color-pressed-hover:#3862e0;--action-button-fill-color-pressed-active:#1d44b8;--settings-list-item-bg:#fff;--settings-list-item-text:#4169e1;--settings-list-item-text-hover:#4169e1;--settings-list-item-border:#dadada;--settings-list-item-bg-active:#e6e6e6;--settings-list-item-bg-hover:#fafafa;--toast-bg:#333;--toast-border:#fafafa;--toast-text:#fff;--mask-bg:#333;--mask-svg-fill:#fff;--mask-opaque-bg:rgba(51,51,51,0.8);--loading-bg:#ededed;--deemphasized-text-color:#666;--focus-outline:#c5d1f6;--very-deemphasized-link-color:rgba(65,105,225,0.6);--very-deemphasized-text-color:rgba(102,102,102,0.6);--status-direct-background:#d2dcf8;--main-theme-color:#4169e1;--warning-color:#e01f19}
|
||||
body{--button-primary-bg:#6081e6;--button-primary-text:#fff;--button-primary-border:#132c76;--button-primary-bg-active:#456ce2;--button-primary-bg-hover:#6988e7;--button-bg:#e6e6e6;--button-text:#333;--button-border:#a7a7a7;--button-bg-active:#bfbfbf;--button-bg-hover:#f2f2f2;--input-border:#dadada;--anchor-text:#4169e1;--main-bg:#fff;--body-bg:#e8edfb;--body-text-color:#333;--main-border:#dadada;--svg-fill:#4169e1;--form-bg:#f7f7f7;--form-border:#c1c1c1;--nav-bg:#4169e1;--nav-border:#214cce;--nav-a-border:#4169e1;--nav-a-selected-border:#fff;--nav-a-selected-bg:#6d8ce8;--nav-svg-fill:#fff;--nav-text-color:#fff;--nav-a-selected-border-hover:#fff;--nav-a-selected-bg-hover:#839deb;--nav-a-bg-hover:#577ae4;--nav-a-border-hover:#4169e1;--nav-svg-fill-hover:#fff;--nav-text-color-hover:#fff;--action-button-fill-color:#90a8ee;--action-button-fill-color-hover:#a2b6f0;--action-button-fill-color-active:#577ae4;--action-button-fill-color-pressed:#2351dc;--action-button-fill-color-pressed-hover:#3862e0;--action-button-fill-color-pressed-active:#1d44b8;--settings-list-item-bg:#fff;--settings-list-item-text:#4169e1;--settings-list-item-text-hover:#4169e1;--settings-list-item-border:#dadada;--settings-list-item-bg-active:#e6e6e6;--settings-list-item-bg-hover:#fafafa;--toast-bg:#333;--toast-border:#fafafa;--toast-text:#fff;--mask-bg:#333;--mask-svg-fill:#fff;--mask-opaque-bg:rgba(51,51,51,0.8);--loading-bg:#ededed;--deemphasized-text-color:#666;--focus-outline:#c5d1f6;--very-deemphasized-link-color:rgba(65,105,225,0.6);--very-deemphasized-text-color:rgba(102,102,102,0.6);--status-direct-background:#d2dcf8;--main-theme-color:#4169e1;--warning-color:#e01f19;--alt-input-bg:rgba(255,255,255,0.7)}
|
||||
body{margin:0;font-family:system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue;font-size:14px;line-height:1.4;color:var(--body-text-color);background:var(--body-bg);position:fixed;left:0;right:0;bottom:0;top:0}.container{overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;will-change:transform;position:absolute;top:72px;left:0;right:0;bottom:0}@media (max-width: 767px){.container{top:62px}}main{position:relative;width:602px;max-width:100vw;padding:0;box-sizing:border-box;margin:30px auto 15px;background:var(--main-bg);border:1px solid var(--main-border);border-radius:1px}@media (max-width: 767px){main{margin:5px auto 15px}}h1,h2,h3,h4,h5,h6{margin:0 0 0.5em 0;font-weight:400;line-height:1.2}h1{font-size:2em}a{color:var(--anchor-text);text-decoration:none}a:visited{color:var(--anchor-text)}a:hover{text-decoration:underline}input{border:1px solid var(--input-border);padding:5px;box-sizing:border-box}button{font-size:1.2em;background:var(--button-bg);border-radius:2px;padding:10px 15px;border:1px solid var(--button-border);cursor:pointer;color:var(--button-text)}button:hover{background:var(--button-bg-hover)}button:active{background:var(--button-bg-active)}button[disabled]{opacity:0.35;pointer-events:none;cursor:not-allowed}button.primary{border:1px solid var(--button-primary-border);background:var(--button-primary-bg);color:var(--button-primary-text)}button.primary:hover{background:var(--button-primary-bg-hover)}button.primary:active{background:var(--button-primary-bg-active)}p,label,input{font-size:1.3em}ul,li,p{padding:0;margin:0}.hidden{opacity:0}*:focus{outline:2px solid var(--focus-outline)}button::-moz-focus-inner{border:0}input:required,input:invalid{box-shadow:none}textarea{font-family:inherit;font-size:inherit;box-sizing:border-box}
|
||||
body.offline,body.theme-hotpants.offline,body.theme-majesty.offline,body.theme-oaken.offline,body.theme-scarlet.offline,body.theme-seafoam.offline,body.theme-gecko.offline{--button-primary-bg:#ababab;--button-primary-text:#fff;--button-primary-border:#4d4d4d;--button-primary-bg-active:#9c9c9c;--button-primary-bg-hover:#b0b0b0;--button-bg:#e6e6e6;--button-text:#333;--button-border:#a7a7a7;--button-bg-active:#bfbfbf;--button-bg-hover:#f2f2f2;--input-border:#dadada;--anchor-text:#999;--main-bg:#fff;--body-bg:#fafafa;--body-text-color:#333;--main-border:#dadada;--svg-fill:#999;--form-bg:#f7f7f7;--form-border:#c1c1c1;--nav-bg:#999;--nav-border:gray;--nav-a-border:#999;--nav-a-selected-border:#fff;--nav-a-selected-bg:#b3b3b3;--nav-svg-fill:#fff;--nav-text-color:#fff;--nav-a-selected-border-hover:#fff;--nav-a-selected-bg-hover:#bfbfbf;--nav-a-bg-hover:#a6a6a6;--nav-a-border-hover:#999;--nav-svg-fill-hover:#fff;--nav-text-color-hover:#fff;--action-button-fill-color:#c7c7c7;--action-button-fill-color-hover:#d1d1d1;--action-button-fill-color-active:#a6a6a6;--action-button-fill-color-pressed:#878787;--action-button-fill-color-pressed-hover:#949494;--action-button-fill-color-pressed-active:#737373;--settings-list-item-bg:#fff;--settings-list-item-text:#999;--settings-list-item-text-hover:#999;--settings-list-item-border:#dadada;--settings-list-item-bg-active:#e6e6e6;--settings-list-item-bg-hover:#fafafa;--toast-bg:#333;--toast-border:#fafafa;--toast-text:#fff;--mask-bg:#333;--mask-svg-fill:#fff;--mask-opaque-bg:rgba(51,51,51,0.8);--loading-bg:#ededed;--deemphasized-text-color:#666;--focus-outline:#bfbfbf;--very-deemphasized-link-color:rgba(153,153,153,0.6);--very-deemphasized-text-color:rgba(102,102,102,0.6);--status-direct-background:#ededed;--main-theme-color:#999;--warning-color:#e01f19}
|
||||
body.offline,body.theme-hotpants.offline,body.theme-majesty.offline,body.theme-oaken.offline,body.theme-scarlet.offline,body.theme-seafoam.offline,body.theme-gecko.offline{--button-primary-bg:#ababab;--button-primary-text:#fff;--button-primary-border:#4d4d4d;--button-primary-bg-active:#9c9c9c;--button-primary-bg-hover:#b0b0b0;--button-bg:#e6e6e6;--button-text:#333;--button-border:#a7a7a7;--button-bg-active:#bfbfbf;--button-bg-hover:#f2f2f2;--input-border:#dadada;--anchor-text:#999;--main-bg:#fff;--body-bg:#fafafa;--body-text-color:#333;--main-border:#dadada;--svg-fill:#999;--form-bg:#f7f7f7;--form-border:#c1c1c1;--nav-bg:#999;--nav-border:gray;--nav-a-border:#999;--nav-a-selected-border:#fff;--nav-a-selected-bg:#b3b3b3;--nav-svg-fill:#fff;--nav-text-color:#fff;--nav-a-selected-border-hover:#fff;--nav-a-selected-bg-hover:#bfbfbf;--nav-a-bg-hover:#a6a6a6;--nav-a-border-hover:#999;--nav-svg-fill-hover:#fff;--nav-text-color-hover:#fff;--action-button-fill-color:#c7c7c7;--action-button-fill-color-hover:#d1d1d1;--action-button-fill-color-active:#a6a6a6;--action-button-fill-color-pressed:#878787;--action-button-fill-color-pressed-hover:#949494;--action-button-fill-color-pressed-active:#737373;--settings-list-item-bg:#fff;--settings-list-item-text:#999;--settings-list-item-text-hover:#999;--settings-list-item-border:#dadada;--settings-list-item-bg-active:#e6e6e6;--settings-list-item-bg-hover:#fafafa;--toast-bg:#333;--toast-border:#fafafa;--toast-text:#fff;--mask-bg:#333;--mask-svg-fill:#fff;--mask-opaque-bg:rgba(51,51,51,0.8);--loading-bg:#ededed;--deemphasized-text-color:#666;--focus-outline:#bfbfbf;--very-deemphasized-link-color:rgba(153,153,153,0.6);--very-deemphasized-text-color:rgba(102,102,102,0.6);--status-direct-background:#ededed;--main-theme-color:#999;--warning-color:#e01f19;--alt-input-bg:rgba(255,255,255,0.7)}
|
||||
|
||||
</style>
|
||||
|
||||
|
|
Loading…
Reference in a new issue