This commit is contained in:
retoor 2025-06-11 17:13:58 +02:00
parent 26a54848f1
commit 3ea4918ca2
6 changed files with 83 additions and 21 deletions

View File

@ -41,7 +41,7 @@ from snek.system.template import (
)
from snek.view.about import AboutHTMLView, AboutMDView
from snek.view.avatar import AvatarView
from snek.view.channel import ChannelAttachmentView, ChannelView
from snek.view.channel import ChannelAttachmentView,ChannelAttachmentUploadView, ChannelView
from snek.view.docs import DocsHTMLView, DocsMDView
from snek.view.drive import DriveApiView, DriveView
from snek.view.index import IndexView
@ -211,10 +211,10 @@ class Application(BaseApplication):
# app.loop = asyncio.get_running_loop()
app.executor = ThreadPoolExecutor(max_workers=200)
app.loop.set_default_executor(self.executor)
for sig in (signal.SIGINT, signal.SIGTERM):
app.loop.add_signal_handler(
sig, lambda: asyncio.create_task(self.services.container.shutdown())
)
#for sig in (signal.SIGINT, signal.SIGTERM):
#app.loop.add_signal_handler(
# sig, lambda: asyncio.create_task(self.services.container.shutdown())
#)
async def create_task(self, task):
await self.tasks.put(task)
@ -286,6 +286,9 @@ class Application(BaseApplication):
self.router.add_view(
"/channel/{channel_uid}/attachment.bin", ChannelAttachmentView
)
self.router.add_view(
"/channel/{channel_uid}/attachment.sock", ChannelAttachmentUploadView
)
self.router.add_view(
"/channel/attachment/{relative_url:.*}", ChannelAttachmentView
)

View File

@ -180,7 +180,13 @@ class ChatInputComponent extends NjetComponent {
this.uploadButton.addEventListener("uploaded", (e) => {
this.dispatchEvent(new CustomEvent("uploaded", e));
});
this.uploadButton.addEventListener("click", (e) => {
e.preventDefault();
this.fileUploadGrid.openFileDialog()
})
this.subscribe("file-uploading", (e) => {
this.fileUploadGrid.style.display = "block";
this.uploadButton.style.display = "none";

View File

@ -1,4 +1,4 @@
import { NjetComponent, NjetDialog } from './njet.js';
import { NjetComponent, NjetDialog } from '/njet.js';
const FUG_ICONS = {
file: 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48"><rect x="8" y="8" width="32" height="40" rx="5" fill="white" stroke="%234af" stroke-width="2"/></svg>'
@ -9,8 +9,11 @@ class FileUploadGrid extends NjetComponent {
super();
this._grid = null;
this._fileInput = null;
this.channelUid = null ;
this.uploadsDone = 0;
this.uploadsStarted = 0;
}
openFileDialog() {
if(this.isBusy){
const dialog = new NjetDialog({
@ -33,11 +36,6 @@ class FileUploadGrid extends NjetComponent {
return true;
}
connectedCallback() {
this.render();
this._fileInput.addEventListener('change', e => this.handleFiles(e.target.files));
}
render() {
// Root wrapper for styling
this.classList.add('fug-root');
@ -55,8 +53,6 @@ class FileUploadGrid extends NjetComponent {
this.appendChild(this._grid);
this.uploadsDone = 0;
this.uploadsStarted = 0;
}
reset(){
@ -75,6 +71,11 @@ class FileUploadGrid extends NjetComponent {
this.uploadsStarted = files.length;
[...files].forEach(file => this.createTile(file));
}
connectedCallback() {
this.channelUid = this.getAttribute('channel');
this.render();
this._fileInput.addEventListener('change', e => this.handleFiles(e.target.files));
}
createTile(file) {
const tile = document.createElement('div');
@ -128,9 +129,10 @@ class FileUploadGrid extends NjetComponent {
startUpload(file, tile, progress) {
this.publish('file-uploading', {file: file, tile: tile, progress: progress});
const ws = new WebSocket(`ws://${location.host}/ws`);
ws.binaryType = 'arraybuffer';
const protocol = location.protocol === "https:" ? "wss://" : "ws://";
const ws = new WebSocket(`${protocol}${location.host}/channel/${this.channelUid}/attachment.sock`);
ws.binaryType = 'arraybuffer';
let sent = 0;
ws.onopen = async () => {

View File

@ -19,15 +19,17 @@ class ComposeFileManager:
async def shutdown(self):
print("Stopping all sessions")
tasks = []
for name in self.list_instances():
proc = self.running_instances.get(name)
if not proc:
continue
if proc['proc'].returncode == None:
print("Stopping",name)
await proc['proc'].stop()
tasks.append(asyncio.create_task(proc['proc'].stop()))
print("Stopped",name,"gracefully")
return tasks
def _load(self):
try:
with open(self.compose_path) as f:

View File

@ -146,6 +146,56 @@ class ChannelAttachmentView(BaseView):
)
class ChannelAttachmentUploadView(BaseView):
async def get(self):
channel_uid = self.request.match_info.get("channel_uid")
user_uid = self.request.session.get("uid")
channel_member = await self.services.channel_member.get(
user_uid=user_uid, channel_uid=channel_uid, deleted_at=None, is_banned=False
)
if not channel_member:
return web.HTTPNotFound()
ws = web.WebSocketResponse()
await ws.prepare(self.request)
file = None
filename = None
msg = await ws.receive()
if not msg.type == web.WSMsgType.TEXT:
return web.HTTPBadRequest()
data = msg.json()
if not data.get('type') == 'start':
return web.HTTPBadRequest()
filename = data['filename']
attachment = await self.services.channel_attachment.create_file(
channel_uid=channel_uid, name=filename, user_uid=user_uid
)
pathlib.Path(attachment["path"]).parent.mkdir(parents=True, exist_ok=True)
async with aiofiles.open(attachment["path"], "wb") as f:
async for msg in ws:
if msg.type == web.WSMsgType.BINARY:
if file is not None:
await file.write(msg.data)
await ws.send_json({"type": "progress", "filename": filename, "bytes": file.tell()})
elif msg.type == web.WSMsgType.TEXT:
data = msg.json()
if data.get('type') == 'end':
await ws.send_json({"type": "done", "filename": filename})
elif msg.type == web.WSMsgType.ERROR:
break
return ws
class ChannelView(BaseView):
async def get(self):
channel_name = self.request.match_info.get("channel")

View File

@ -509,8 +509,7 @@ class RPCView(BaseView):
async for msg in ws:
if msg.type == web.WSMsgType.TEXT:
try:
async with Profiler():
await rpc(msg.json())
await rpc(msg.json())
except Exception as ex:
print("Deleting socket", ex, flush=True)
logger.exception(ex)