mirror of
https://github.com/wbbaddons/Tims-Chat.git
synced 2024-12-21 21:30:08 +00:00
Implement attachment upload UI skeleton
This commit is contained in:
parent
d07d18a0cb
commit
d5195c0562
@ -25,6 +25,13 @@
|
||||
class RoomPage extends \wcf\page\AbstractPage {
|
||||
use TConfiguredPage;
|
||||
|
||||
/**
|
||||
* Almost dummy attachment handler (used in language variable)
|
||||
*
|
||||
* @var \wcf\system\attachment\AttachmentHandler
|
||||
*/
|
||||
public $attachmentHandler;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@ -65,7 +72,7 @@ public function readParameters() {
|
||||
*/
|
||||
public function checkPermissions() {
|
||||
parent::checkPermissions();
|
||||
|
||||
|
||||
$package = \wcf\data\package\PackageCache::getInstance()->getPackageByIdentifier('be.bastelstu.chat');
|
||||
if (stripos($package->packageVersion, 'Alpha') !== false) {
|
||||
$sql = "SELECT COUNT(*) FROM wcf".WCF_N."_user";
|
||||
@ -91,6 +98,9 @@ public function readData() {
|
||||
|
||||
parent::readData();
|
||||
|
||||
// This attachment handler gets only used for the language variable `wcf.attachment.upload.limits`!
|
||||
$this->attachmentHandler = new \wcf\system\attachment\AttachmentHandler('be.bastelstu.chat.message', 0, 'DEADC0DE00000000DEADC0DE00000000DEADC0DE', $this->room->roomID);
|
||||
|
||||
$pushHandler = \wcf\system\push\PushHandler::getInstance();
|
||||
$pushHandler->joinChannel('be.bastelstu.chat');
|
||||
$pushHandler->joinChannel('be.bastelstu.chat.room-'.$this->room->roomID);
|
||||
@ -104,6 +114,7 @@ public function assignVariables() {
|
||||
|
||||
WCF::getTPL()->assign([ 'room' => $this->room
|
||||
, 'config' => $this->getConfig()
|
||||
, 'attachmentHandler' => $this->attachmentHandler
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ define([ './Chat/console'
|
||||
, './Chat/ProfileStore'
|
||||
, './Chat/Room'
|
||||
, './Chat/Template'
|
||||
, './Chat/Ui/Attachment/Upload'
|
||||
, './Chat/Ui/AutoAway'
|
||||
, './Chat/Ui/Chat'
|
||||
, './Chat/Ui/ConnectionWarning'
|
||||
@ -43,7 +44,7 @@ define([ './Chat/console'
|
||||
, './Chat/Ui/UserActionDropdownHandler'
|
||||
, './Chat/Ui/UserList'
|
||||
], function (console, Bottle, Push, Core, Language, RepeatingTimer, CoreUser, Autocompleter,
|
||||
CommandHandler, Throttle, Message, Messenger, ParseError, ProfileStore, Room, Template, UiAutoAway, Ui,
|
||||
CommandHandler, Throttle, Message, Messenger, ParseError, ProfileStore, Room, Template, UiAttachmentUpload, UiAutoAway, Ui,
|
||||
UiConnectionWarning, ErrorDialog, UiInput, UiInputAutocompleter, UiMessageStream, UiMessageActionDelete, UiMobile, UiNotification,
|
||||
UiReadMarker, UiSettings, UiTopic, UiUserActionDropdownHandler, UiUserList) {
|
||||
"use strict";
|
||||
@ -85,6 +86,7 @@ define([ './Chat/console'
|
||||
this.service('UiTopic', UiTopic)
|
||||
this.service('UiUserActionDropdownHandler', UiUserActionDropdownHandler)
|
||||
this.service('UiUserList', UiUserList)
|
||||
this.service('UiAttachmentUpload', UiAttachmentUpload)
|
||||
|
||||
// Register Models
|
||||
this.bottle.instanceFactory('Message', (container, m) => {
|
||||
|
195
files_wcf/js/Bastelstu.be/Chat/Ui/Attachment/Upload.js
Normal file
195
files_wcf/js/Bastelstu.be/Chat/Ui/Attachment/Upload.js
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2020 Tim Düsterhus.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License
|
||||
* included in the LICENSE file.
|
||||
*
|
||||
* Change Date: 2024-11-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source
|
||||
* License, use of this software will be governed by version 2
|
||||
* or later of the General Public License.
|
||||
*/
|
||||
|
||||
define([ 'WoltLabSuite/Core/Language'
|
||||
, 'WoltLabSuite/Core/Upload'
|
||||
, 'WoltLabSuite/Core/Dom/Change/Listener'
|
||||
, 'WoltLabSuite/Core/Dom/Util'
|
||||
, 'WoltLabSuite/Core/Ui/Dialog'
|
||||
, '../../DataStructure/EventEmitter'
|
||||
], function(Language, Upload, DomChangeListener, DomUtil, Dialog, EventEmitter) {
|
||||
"use strict";
|
||||
|
||||
const DIALOG_BUTTON_ID = 'chatAttachmentUploadButton'
|
||||
const DIALOG_CONTAINER_ID = 'chatAttachmentUploadDialog'
|
||||
|
||||
const DEPENDENCIES = [ 'Room' ];
|
||||
class UiAttachmentUpload extends Upload {
|
||||
constructor(room) {
|
||||
const buttonContainer = document.querySelector(`#${DIALOG_CONTAINER_ID} > .upload`)
|
||||
const buttonContainerId = DomUtil.identify(buttonContainer)
|
||||
|
||||
const previewContainer = document.querySelector(`#${DIALOG_CONTAINER_ID} > .attachmentPreview`)
|
||||
const previewContainerId = DomUtil.identify(previewContainer)
|
||||
|
||||
super(buttonContainerId, previewContainerId, {
|
||||
className: 'wcf\\data\\attachment\\AttachmentAction',
|
||||
acceptableFiles: [ '.png', '.gif', '.jpg', '.jpeg' ]
|
||||
})
|
||||
|
||||
this.room = room
|
||||
this.previewContainer = previewContainer
|
||||
}
|
||||
|
||||
bootstrap() {
|
||||
this.uploadDescription = document.querySelector(`#${DIALOG_CONTAINER_ID} > small`)
|
||||
|
||||
const button = document.getElementById(DIALOG_BUTTON_ID)
|
||||
const container = document.getElementById(DIALOG_CONTAINER_ID)
|
||||
|
||||
elHide(container)
|
||||
container.classList.remove('jsStaticDialogContent')
|
||||
container.dataset.isStaticDialog = 'true'
|
||||
|
||||
if (button) {
|
||||
button.addEventListener('click', (event) => {
|
||||
event.preventDefault()
|
||||
|
||||
Dialog.openStatic(container.id, null, {
|
||||
title: elData(container, 'title'),
|
||||
onShow: () => this.showDialog()
|
||||
})
|
||||
})
|
||||
|
||||
const deleteAction = new WCF.Action.Delete('wcf\\data\\attachment\\AttachmentAction', `#${this.previewContainer.id} > p`)
|
||||
deleteAction.setCallback(() => this.closeDialog())
|
||||
}
|
||||
}
|
||||
|
||||
closeDialog() {
|
||||
if (Dialog.getDialog(DIALOG_CONTAINER_ID)) {
|
||||
Dialog.close(DIALOG_CONTAINER_ID)
|
||||
}
|
||||
}
|
||||
|
||||
showDialog() {
|
||||
if (this._button.parentNode) {
|
||||
this._removeButton()
|
||||
}
|
||||
|
||||
this._target.innerHTML = ''
|
||||
this._createButton()
|
||||
elShow(this.uploadDescription)
|
||||
}
|
||||
|
||||
async send(event) {
|
||||
event.preventDefault()
|
||||
const parameters = { promise: Promise.resolve() }
|
||||
this.emit('send', parameters)
|
||||
|
||||
try {
|
||||
await parameters.promise
|
||||
this.closeDialog()
|
||||
}
|
||||
catch (error) {
|
||||
// TODO: Error handling
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
createButtonGroup(uploadId, objectID) {
|
||||
const buttonGroup = document.createElement('ul')
|
||||
buttonGroup.classList.add('buttonGroup')
|
||||
|
||||
let li = document.createElement('li')
|
||||
const cancelButton = document.createElement('span')
|
||||
cancelButton.classList.add('button', 'jsDeleteButton')
|
||||
cancelButton.dataset.objectId = objectID
|
||||
cancelButton.dataset.eventName = 'attachment'
|
||||
cancelButton.innerText = Language.get('wcf.global.button.cancel')
|
||||
li.appendChild(cancelButton)
|
||||
buttonGroup.appendChild(li)
|
||||
|
||||
li = document.createElement('li')
|
||||
const sendButton = document.createElement('span')
|
||||
sendButton.classList.add('button')
|
||||
sendButton.dataset.objectId = objectID
|
||||
sendButton.innerText = Language.get('wcf.global.button.submit')
|
||||
sendButton.addEventListener('click', (e) => this.send(e))
|
||||
li.appendChild(sendButton)
|
||||
buttonGroup.appendChild(li)
|
||||
|
||||
const target = this._fileElements[uploadId][0]
|
||||
target.appendChild(buttonGroup)
|
||||
|
||||
DomChangeListener.trigger()
|
||||
}
|
||||
|
||||
/**
|
||||
* @see WoltLabSuite/Core/Upload#_getParameters
|
||||
*/
|
||||
_getParameters() {
|
||||
const hash = [ ...crypto.getRandomValues(new Uint8Array(20)) ]
|
||||
.map(m => ('0' + m.toString(16)).slice(-2))
|
||||
.join('')
|
||||
|
||||
return { objectType: "be.bastelstu.chat.message"
|
||||
, parentObjectID: this.room.roomID
|
||||
, tmpHash: hash
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see WoltLabSuite/Core/Upload#_success
|
||||
*/
|
||||
_success(uploadId, data, responseText, xhr, requestOptions) {
|
||||
if (data.returnValues?.errors?.[0]) {
|
||||
const error = data.returnValues.errors[0]
|
||||
|
||||
elInnerError(this._button, Language.get(`wcf.attachment.upload.error.${error.errorType}`, {
|
||||
filename: error.filename
|
||||
}))
|
||||
}
|
||||
else {
|
||||
elInnerError(this._button, '')
|
||||
}
|
||||
|
||||
if (data.returnValues?.attachments?.[uploadId]) {
|
||||
this._removeButton()
|
||||
elHide(this.uploadDescription)
|
||||
|
||||
const attachment = data.returnValues.attachments[uploadId]
|
||||
const url = attachment.thumbnailURL || attachment.tinyURL || attachment.url
|
||||
|
||||
if (!url) {
|
||||
throw new Error('Missing image URL')
|
||||
}
|
||||
|
||||
const target = this._fileElements[uploadId][0]
|
||||
const progress = target.querySelector(':scope > progress')
|
||||
|
||||
const img = document.createElement('img')
|
||||
img.setAttribute('src', url)
|
||||
img.setAttribute('alt', '')
|
||||
|
||||
if (url === attachment.thumbnailURL) {
|
||||
img.classList.add('attachmentThumbnail')
|
||||
}
|
||||
else if (url === attachment.tinyURL) {
|
||||
img.classList.add('attachmentTinyThumbnail')
|
||||
}
|
||||
|
||||
img.dataset.width = attachment.width
|
||||
img.dataset.height = attachment.height
|
||||
|
||||
DomUtil.replaceElement(progress, img)
|
||||
|
||||
this.createButtonGroup(uploadId, attachment.attachmentID)
|
||||
}
|
||||
}
|
||||
}
|
||||
UiAttachmentUpload.DEPENDENCIES = DEPENDENCIES
|
||||
EventEmitter(UiAttachmentUpload.prototype)
|
||||
|
||||
return UiAttachmentUpload
|
||||
})
|
@ -14,7 +14,8 @@
|
||||
define([ '../Ui' ], function (Ui) {
|
||||
"use strict";
|
||||
|
||||
const DEPENDENCIES = [ 'UiAutoAway'
|
||||
const DEPENDENCIES = [ 'UiAttachmentUpload'
|
||||
, 'UiAutoAway'
|
||||
, 'UiConnectionWarning'
|
||||
, 'UiInput'
|
||||
, 'UiInputAutocompleter'
|
||||
@ -29,7 +30,7 @@ define([ '../Ui' ], function (Ui) {
|
||||
, 'UiUserList'
|
||||
]
|
||||
class Chat extends Ui {
|
||||
constructor(autoAway, connectionWarning, input, autocompleter, messageStream, messageActionDelete, mobile, notification, readMarker, settings, topic, userActionDropdownHandler, userList) {
|
||||
constructor(attachmentUpload, autoAway, connectionWarning, input, autocompleter, messageStream, messageActionDelete, mobile, notification, readMarker, settings, topic, userActionDropdownHandler, userList) {
|
||||
super()
|
||||
|
||||
this.actionDropdownHandler = userActionDropdownHandler
|
||||
@ -45,6 +46,7 @@ define([ '../Ui' ], function (Ui) {
|
||||
this.settings = settings
|
||||
this.topic = topic
|
||||
this.userList = userList
|
||||
this.attachmentUpload = attachmentUpload
|
||||
}
|
||||
|
||||
bootstrap() {
|
||||
@ -61,6 +63,7 @@ define([ '../Ui' ], function (Ui) {
|
||||
this.settings.bootstrap()
|
||||
this.topic.bootstrap()
|
||||
this.userList.bootstrap()
|
||||
this.attachmentUpload.bootstrap()
|
||||
}
|
||||
}
|
||||
Chat.DEPENDENCIES = DEPENDENCIES
|
||||
|
19
templates/__attachmentDialog.tpl
Normal file
19
templates/__attachmentDialog.tpl
Normal file
@ -0,0 +1,19 @@
|
||||
<div id="chatAttachmentUploadDialog" class="jsStaticDialogContent" data-title="{lang}wcf.attachment.attachments{/lang}">
|
||||
<div class="attachmentPreview"></div>
|
||||
|
||||
{* placeholder for the upload button *}
|
||||
<div class="upload"></div>
|
||||
<small>{lang}wcf.attachment.upload.limits{/lang}</small>
|
||||
</div>
|
||||
<script data-relocate="true">
|
||||
require([ 'Language' ], function (Language) {
|
||||
Language.addObject({
|
||||
'wcf.attachment.upload.error.invalidExtension': '{lang}wcf.attachment.upload.error.invalidExtension{/lang}',
|
||||
'wcf.attachment.upload.error.tooLarge': '{lang}wcf.attachment.upload.error.tooLarge{/lang}',
|
||||
'wcf.attachment.upload.error.reachedLimit': '{lang}wcf.attachment.upload.error.reachedLimit{/lang}',
|
||||
'wcf.attachment.upload.error.reachedRemainingLimit': '{lang}wcf.attachment.upload.error.reachedRemainingLimit{/lang}',
|
||||
'wcf.attachment.upload.error.uploadFailed': '{lang}wcf.attachment.upload.error.uploadFailed{/lang}',
|
||||
'wcf.attachment.upload.error.uploadPhpLimit': '{lang}wcf.attachment.upload.error.uploadPhpLimit{/lang}',
|
||||
})
|
||||
})
|
||||
</script>
|
@ -4,6 +4,9 @@
|
||||
<li><a class="button" href="#" data-module="Bastelstu.be/Chat/Ui/Settings/FullscreenButton"><span class="icon icon16 fa-arrows-alt"></span> <span>{lang}chat.room.button.fullscreen{/lang}</span></a></li>
|
||||
<li><a class="button" href="#" data-module="Bastelstu.be/Chat/Ui/Settings/NotificationsButton"><span class="icon icon16 fa-bell-o"></span> <span>{lang}chat.room.button.notifications{/lang}</span></a></li>
|
||||
<li><a class="button" href="#" data-module="Bastelstu.be/Chat/Ui/Settings/AutoscrollButton"><span class="icon icon16 fa-arrow-down"></span> <span>{lang}chat.room.button.autoscroll{/lang}</span></a></li>
|
||||
{if $__wcf->getSession()->getPermission('user.chat.canAttach')}
|
||||
<li><a id="chatAttachmentUploadButton" class="button" href="#"><span class="icon icon16 fa-paperclip"></span> <span>{lang}wcf.attachment.attachments{/lang}</span></a>
|
||||
{/if}
|
||||
{event name='buttons'}
|
||||
</ul>
|
||||
</nav>
|
||||
|
@ -71,6 +71,7 @@
|
||||
{include file='messageTypes' application='chat'}
|
||||
{include file='userList' application='chat'}
|
||||
{include file='userListDropdownMenuItems' application='chat'}
|
||||
{include file='__attachmentDialog' application='chat'}
|
||||
|
||||
{if !ENABLE_DEBUG_MODE}{js application='wcf' file='Bastelstu.be.Chat'}{/if}
|
||||
<script data-relocate="true">
|
||||
|
Loading…
Reference in New Issue
Block a user