make file transfer initiate automatically

This commit is contained in:
marlon-erler
2026-04-06 15:50:13 +00:00
parent 7eaf07918c
commit 3fb9785882
15 changed files with 112 additions and 53 deletions
BIN
View File
Binary file not shown.
+44 -17
View File
@@ -2244,7 +2244,9 @@
searchTerm searchTerm
]; ];
this.storageModel.write(suggestionPath, ""); this.storageModel.write(suggestionPath, "");
if (!this.coreViewModel.boardFilterStringSuggestions.value.has(searchTerm)) { if (!this.coreViewModel.boardFilterStringSuggestions.value.has(
searchTerm
)) {
this.coreViewModel.boardFilterStringSuggestions.add(searchTerm); this.coreViewModel.boardFilterStringSuggestions.add(searchTerm);
} }
const lastSearchPath = this.getLastSearchPath(); const lastSearchPath = this.getLastSearchPath();
@@ -2517,6 +2519,7 @@
reloadAppButton: "Reload App", reloadAppButton: "Reload App",
fileVersionLabel: "Version", fileVersionLabel: "Version",
searchLabel: "Search", searchLabel: "Search",
waitingLabel: "Waiting...",
restoreConnection: "Restore connection" restoreConnection: "Restore connection"
}, },
regional: { regional: {
@@ -2566,7 +2569,6 @@
selectionDescription: "Select the data that you want to transfer.", selectionDescription: "Select the data that you want to transfer.",
dataEntryDescription: "Enter this data on the other device.", dataEntryDescription: "Enter this data on the other device.",
dataEntryInputDescription: "Enter the data displayed on the other device.", dataEntryInputDescription: "Enter the data displayed on the other device.",
readyToReceiveDescription: "Click 'send' on the other device.",
notConnectedError: "You are not connected to any server.", notConnectedError: "You are not connected to any server.",
/// ///
fromThisDeviceButton: "From this device", fromThisDeviceButton: "From this device",
@@ -2707,6 +2709,7 @@
reloadAppButton: "Neu laden", reloadAppButton: "Neu laden",
fileVersionLabel: "Version", fileVersionLabel: "Version",
searchLabel: "Suche", searchLabel: "Suche",
waitingLabel: "Warten...",
restoreConnection: "Verbindung wiederherstellen" restoreConnection: "Verbindung wiederherstellen"
}, },
regional: { regional: {
@@ -2753,7 +2756,6 @@
selectionDescription: "W\xE4hle die Daten aus, die du \xFCbertragen m\xF6chtest.", selectionDescription: "W\xE4hle die Daten aus, die du \xFCbertragen m\xF6chtest.",
dataEntryDescription: "Gib diese Informationen auf dem anderen Ger\xE4t ein.", dataEntryDescription: "Gib diese Informationen auf dem anderen Ger\xE4t ein.",
dataEntryInputDescription: "Gib die auf dem anderen Ger\xE4t angezeigten Informationen ein.", dataEntryInputDescription: "Gib die auf dem anderen Ger\xE4t angezeigten Informationen ein.",
readyToReceiveDescription: "Klicke auf dem anderen Ger\xE4t auf 'Senden'.",
notConnectedError: "Du bist mit keinem Server verbunden.", notConnectedError: "Du bist mit keinem Server verbunden.",
fromThisDeviceButton: "Von diesem Ger\xE4t", fromThisDeviceButton: "Von diesem Ger\xE4t",
toThisDeviceButton: "An dieses Ger\xE4t", toThisDeviceButton: "An dieses Ger\xE4t",
@@ -2878,6 +2880,7 @@
reloadAppButton: "Recargar app", reloadAppButton: "Recargar app",
fileVersionLabel: "Versi\xF3n", fileVersionLabel: "Versi\xF3n",
searchLabel: "Buscar", searchLabel: "Buscar",
waitingLabel: "Esperando...",
restoreConnection: "Conectar de nuevo" restoreConnection: "Conectar de nuevo"
}, },
regional: { regional: {
@@ -2924,7 +2927,6 @@
selectionDescription: "Selecciona los datos que quieres transferir.", selectionDescription: "Selecciona los datos que quieres transferir.",
dataEntryDescription: "Introduce estos datos en el otro dispositivo.", dataEntryDescription: "Introduce estos datos en el otro dispositivo.",
dataEntryInputDescription: "Introduce los datos mostrados en el otro dispositivo.", dataEntryInputDescription: "Introduce los datos mostrados en el otro dispositivo.",
readyToReceiveDescription: "Haz clic en 'enviar' en el otro dispositivo.",
notConnectedError: "No est\xE1s conectado a ning\xFAn servidor.", notConnectedError: "No est\xE1s conectado a ning\xFAn servidor.",
fromThisDeviceButton: "Desde este dispositivo", fromThisDeviceButton: "Desde este dispositivo",
toThisDeviceButton: "A este dispositivo", toThisDeviceButton: "A este dispositivo",
@@ -3104,11 +3106,14 @@
this.hasUnreadMessages.value = hasUnreadMessages; this.hasUnreadMessages.value = hasUnreadMessages;
}; };
this.subscribeReadStatus = () => { this.subscribeReadStatus = () => {
createProxyState([this.selectedPage, this.chatListViewModel.selectedChat], () => { createProxyState(
if (this.chatListViewModel.selectedChat.value != this) return; [this.selectedPage, this.chatListViewModel.selectedChat],
if (this.selectedPage.value != "messages" /* Messages */) return; () => {
this.setReadStatus(false); if (this.chatListViewModel.selectedChat.value != this) return;
}); if (this.selectedPage.value != "messages" /* Messages */) return;
this.setReadStatus(false);
}
);
}; };
this.storageModel = storageModel2; this.storageModel = storageModel2;
this.chatModel = chatModel; this.chatModel = chatModel;
@@ -5147,6 +5152,7 @@
this.connectToAddress(this.serverAddressInput.value); this.connectToAddress(this.serverAddressInput.value);
}; };
this.connectToAddress = (address) => { this.connectToAddress = (address) => {
console.log(address);
this.connectionModel.connect(address); this.connectionModel.connect(address);
}; };
this.disconnect = () => { this.disconnect = () => {
@@ -5282,6 +5288,7 @@
this.showTransferDataModal = () => { this.showTransferDataModal = () => {
this.presentedModal.value = 2 /* TransferDataDisplay */; this.presentedModal.value = 2 /* TransferDataDisplay */;
this.getTransferData(); this.getTransferData();
this.fileTransferModel.prepareToSend();
}; };
this.initiateTransfer = () => { this.initiateTransfer = () => {
this.presentedModal.value = 3 /* TransferDisplay */; this.presentedModal.value = 3 /* TransferDisplay */;
@@ -5316,6 +5323,9 @@
this.fileTransferModel.fileHandlerManager.addHandler( this.fileTransferModel.fileHandlerManager.addHandler(
this.handleReceivedFile this.handleReceivedFile
); );
this.fileTransferModel.readyToSendHandlerManager.addHandler(
() => this.initiateTransfer()
);
} }
}; };
@@ -5463,11 +5473,10 @@
), /* @__PURE__ */ createElement( ), /* @__PURE__ */ createElement(
"button", "button",
{ {
class: "primary flex", disabled: true,
"on:click": fileTransferViewModel2.initiateTransfer class: "flex"
}, },
translations.dataTransferModal.sendButton, translations.general.waitingLabel
/* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward")
)))); ))));
} }
function TransferDisplayModal(fileTransferViewModel2) { function TransferDisplayModal(fileTransferViewModel2) {
@@ -5554,7 +5563,7 @@
[fileTransferViewModel2.presentedModal], [fileTransferViewModel2.presentedModal],
() => fileTransferViewModel2.presentedModal.value == 5 /* ReceptionDisplay */ () => fileTransferViewModel2.presentedModal.value == 5 /* ReceptionDisplay */
); );
return /* @__PURE__ */ createElement("div", { class: "modal", "toggle:open": isPresented }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, translations.dataTransferModal.transferDataHeadline), /* @__PURE__ */ createElement("p", { class: "secondary" }, translations.dataTransferModal.readyToReceiveDescription), /* @__PURE__ */ createElement( return /* @__PURE__ */ createElement("div", { class: "modal", "toggle:open": isPresented }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, translations.dataTransferModal.transferDataHeadline), /* @__PURE__ */ createElement(
"p", "p",
{ {
class: "secondary", class: "secondary",
@@ -5573,10 +5582,12 @@
} }
// src/Model/Global/fileTransferModel.ts // src/Model/Global/fileTransferModel.ts
var FileTransferModel = class { var FileTransferModel = class _FileTransferModel {
// init // init
constructor(storageModel2, connectionModel2) { constructor(storageModel2, connectionModel2) {
this.fileHandlerManager = new HandlerManager(); this.fileHandlerManager = new HandlerManager();
this.readyToSendHandlerManager = new HandlerManager();
this.direction = 0 /* Send */;
// general // general
this.generateTransferData = () => { this.generateTransferData = () => {
const transferData = { const transferData = {
@@ -5586,15 +5597,29 @@
this.transferData = transferData; this.transferData = transferData;
return transferData; return transferData;
}; };
this.prepareToSend = () => {
this.direction = 0 /* Send */;
this.connectionModel.addChannel(this.transferData.channel);
};
this.prepareToReceive = (transferData) => { this.prepareToReceive = (transferData) => {
this.direction = 1 /* Receive */;
this.connectionModel.addChannel(transferData.channel); this.connectionModel.addChannel(transferData.channel);
this.transferData = transferData; this.transferData = transferData;
this.connectionModel.sendPlainMessage(
transferData.channel,
_FileTransferModel.READY_MESSAGE
);
}; };
// handlers // handlers
this.handleMessage = (data) => { this.handleMessage = (data) => {
console.log(this.transferData);
if (data.messageChannel != this.transferData.channel) return;
if (data.messageBody == _FileTransferModel.READY_MESSAGE && this.direction == 0 /* Send */) {
console.log("TRIGGER");
this.readyToSendHandlerManager.trigger(true);
}
if (this.transferData == void 0) return; if (this.transferData == void 0) return;
if (data.messageBody == void 0) return; if (data.messageBody == void 0) return;
if (data.messageChannel != this.transferData.channel) return;
this.handleFile(data.messageBody); this.handleFile(data.messageBody);
}; };
this.handleFile = async (encryptedFileData) => { this.handleFile = async (encryptedFileData) => {
@@ -5603,7 +5628,6 @@
encryptedFileData, encryptedFileData,
this.transferData.key this.transferData.key
); );
console.log(decrypted);
const parsed = parse(decrypted); const parsed = parse(decrypted);
const isFileData = checkMatchesObjectStructure( const isFileData = checkMatchesObjectStructure(
parsed, parsed,
@@ -5653,6 +5677,9 @@
this.handleMessage this.handleMessage
); );
} }
static {
this.READY_MESSAGE = "ready";
}
}; };
var FileDataReference = { var FileDataReference = {
path: [""], path: [""],
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"dependencies": { "dependencies": {
"@types/uuid": "^10.0.0", "@types/uuid": "^10.0.0",
"bloatless-react": "^1.3.10", "bloatless-react": "^1.3.11",
"esbuild": "^0.23.0", "esbuild": "^0.23.0",
"udn-frontend": "^1.0.9", "udn-frontend": "^1.0.9",
"uuid": "^10.0.0" "uuid": "^10.0.0"
+31 -3
View File
@@ -17,9 +17,13 @@ export default class FileTransferModel {
storageModel: StorageModel; storageModel: StorageModel;
connectionModel: ConnectionModel; connectionModel: ConnectionModel;
static READY_MESSAGE = "ready";
// data // data
transferData: TransferData | undefined; transferData: TransferData | undefined;
fileHandlerManager: HandlerManager<string> = new HandlerManager(); fileHandlerManager: HandlerManager<string> = new HandlerManager();
readyToSendHandlerManager: HandlerManager<boolean> = new HandlerManager();
direction: TransferDirections = TransferDirections.Send;
// general // general
generateTransferData = (): TransferData => { generateTransferData = (): TransferData => {
@@ -31,16 +35,36 @@ export default class FileTransferModel {
return transferData; return transferData;
}; };
prepareToReceive = (transferData: TransferData) => { prepareToSend = (): void => {
this.direction = TransferDirections.Send;
this.connectionModel.addChannel(this.transferData.channel);
};
prepareToReceive = (transferData: TransferData): void => {
this.direction = TransferDirections.Receive;
this.connectionModel.addChannel(transferData.channel); this.connectionModel.addChannel(transferData.channel);
this.transferData = transferData; this.transferData = transferData;
this.connectionModel.sendPlainMessage(
transferData.channel,
FileTransferModel.READY_MESSAGE,
);
}; };
// handlers // handlers
handleMessage = (data: Message): void => { handleMessage = (data: Message): void => {
console.log(this.transferData);
if (data.messageChannel != this.transferData.channel) return;
if (
data.messageBody == FileTransferModel.READY_MESSAGE &&
this.direction == TransferDirections.Send
) {
console.log("TRIGGER");
this.readyToSendHandlerManager.trigger(true);
}
if (this.transferData == undefined) return; if (this.transferData == undefined) return;
if (data.messageBody == undefined) return; if (data.messageBody == undefined) return;
if (data.messageChannel != this.transferData.channel) return;
this.handleFile(data.messageBody); this.handleFile(data.messageBody);
}; };
@@ -52,7 +76,6 @@ export default class FileTransferModel {
encryptedFileData, encryptedFileData,
this.transferData.key, this.transferData.key,
); );
console.log(decrypted);
const parsed: any = parse(decrypted); const parsed: any = parse(decrypted);
const isFileData: boolean = checkMatchesObjectStructure( const isFileData: boolean = checkMatchesObjectStructure(
@@ -131,3 +154,8 @@ export const FileDataReference: FileData = {
path: [""], path: [""],
body: "", body: "",
}; };
export enum TransferDirections {
Send,
Receive,
}
+2 -13
View File
@@ -281,12 +281,8 @@ function TransferDataDisplayModal(
> >
{translations.general.backButton} {translations.general.backButton}
</button> </button>
<button <button disabled class="flex">
class="primary flex" {translations.general.waitingLabel}
on:click={fileTransferViewModel.initiateTransfer}
>
{translations.dataTransferModal.sendButton}
<span class="icon">arrow_forward</span>
</button> </button>
</div> </div>
</div> </div>
@@ -461,13 +457,6 @@ function DataReceptionModal(fileTransferViewModel: FileTransferViewModel) {
{translations.dataTransferModal.transferDataHeadline} {translations.dataTransferModal.transferDataHeadline}
</h2> </h2>
<p class="secondary">
{
translations.dataTransferModal
.readyToReceiveDescription
}
</p>
<p <p
class="secondary" class="secondary"
subscribe:innerText={ subscribe:innerText={
+1 -1
View File
@@ -25,7 +25,7 @@ export function TaskSettingsModal(taskViewModel: TaskViewModel) {
}; };
return ( return (
<div class="modal" open> <div class="modal" open metakey:s={taskViewModel.closeAndSave}>
<div> <div>
<main> <main>
<h2>{translations.chatPage.task.taskSettingsHeadline}</h2> <h2>{translations.chatPage.task.taskSettingsHeadline}</h2>
+3 -5
View File
@@ -21,6 +21,7 @@ const englishTranslations = {
fileVersionLabel: "Version", fileVersionLabel: "Version",
searchLabel: "Search", searchLabel: "Search",
waitingLabel: "Waiting...",
restoreConnection: "Restore connection", restoreConnection: "Restore connection",
}, },
@@ -89,7 +90,6 @@ const englishTranslations = {
dataEntryDescription: "Enter this data on the other device.", dataEntryDescription: "Enter this data on the other device.",
dataEntryInputDescription: dataEntryInputDescription:
"Enter the data displayed on the other device.", "Enter the data displayed on the other device.",
readyToReceiveDescription: "Click 'send' on the other device.",
notConnectedError: "You are not connected to any server.", notConnectedError: "You are not connected to any server.",
@@ -298,6 +298,7 @@ const allTranslations: { [language: string]: typeof englishTranslations } = {
fileVersionLabel: "Version", fileVersionLabel: "Version",
searchLabel: "Suche", searchLabel: "Suche",
waitingLabel: "Warten...",
restoreConnection: "Verbindung wiederherstellen", restoreConnection: "Verbindung wiederherstellen",
}, },
@@ -362,8 +363,6 @@ const allTranslations: { [language: string]: typeof englishTranslations } = {
"Gib diese Informationen auf dem anderen Gerät ein.", "Gib diese Informationen auf dem anderen Gerät ein.",
dataEntryInputDescription: dataEntryInputDescription:
"Gib die auf dem anderen Gerät angezeigten Informationen ein.", "Gib die auf dem anderen Gerät angezeigten Informationen ein.",
readyToReceiveDescription:
"Klicke auf dem anderen Gerät auf 'Senden'.",
notConnectedError: "Du bist mit keinem Server verbunden.", notConnectedError: "Du bist mit keinem Server verbunden.",
@@ -543,6 +542,7 @@ const allTranslations: { [language: string]: typeof englishTranslations } = {
fileVersionLabel: "Versión", fileVersionLabel: "Versión",
searchLabel: "Buscar", searchLabel: "Buscar",
waitingLabel: "Esperando...",
restoreConnection: "Conectar de nuevo", restoreConnection: "Conectar de nuevo",
}, },
@@ -607,8 +607,6 @@ const allTranslations: { [language: string]: typeof englishTranslations } = {
"Introduce estos datos en el otro dispositivo.", "Introduce estos datos en el otro dispositivo.",
dataEntryInputDescription: dataEntryInputDescription:
"Introduce los datos mostrados en el otro dispositivo.", "Introduce los datos mostrados en el otro dispositivo.",
readyToReceiveDescription:
"Haz clic en 'enviar' en el otro dispositivo.",
notConnectedError: "No estás conectado a ningún servidor.", notConnectedError: "No estás conectado a ningún servidor.",
+9 -6
View File
@@ -116,12 +116,15 @@ export default class ChatViewModel {
}; };
subscribeReadStatus = (): void => { subscribeReadStatus = (): void => {
React.createProxyState([this.selectedPage, this.chatListViewModel.selectedChat], () => { React.createProxyState(
if (this.chatListViewModel.selectedChat.value != this) return; [this.selectedPage, this.chatListViewModel.selectedChat],
if (this.selectedPage.value != ChatPageType.Messages) return; () => {
this.setReadStatus(false); if (this.chatListViewModel.selectedChat.value != this) return;
}) if (this.selectedPage.value != ChatPageType.Messages) return;
} this.setReadStatus(false);
},
);
};
// init // init
constructor( constructor(
@@ -52,6 +52,7 @@ export default class ConnectionViewModel {
}; };
connectToAddress = (address: string): void => { connectToAddress = (address: string): void => {
console.log(address);
this.connectionModel.connect(address); this.connectionModel.connect(address);
}; };
+2 -1
View File
@@ -6,7 +6,8 @@ export default class CoreViewModel {
// SUGGESTIONS // SUGGESTIONS
// boards & tasks // boards & tasks
boardSearchSuggestions: React.ListState<string> = new React.ListState(); boardFilterStringSuggestions: React.ListState<string> =
new React.ListState();
taskCategorySuggestions: React.ListState<string> = new React.ListState(); taskCategorySuggestions: React.ListState<string> = new React.ListState();
taskStatusSuggestions: React.ListState<string> = new React.ListState(); taskStatusSuggestions: React.ListState<string> = new React.ListState();
@@ -128,6 +128,7 @@ export default class FileTransferViewModel {
showTransferDataModal = (): void => { showTransferDataModal = (): void => {
this.presentedModal.value = FileTransferModal.TransferDataDisplay; this.presentedModal.value = FileTransferModal.TransferDataDisplay;
this.getTransferData(); this.getTransferData();
this.fileTransferModel.prepareToSend();
}; };
initiateTransfer = (): void => { initiateTransfer = (): void => {
@@ -176,6 +177,10 @@ export default class FileTransferViewModel {
this.fileTransferModel.fileHandlerManager.addHandler( this.fileTransferModel.fileHandlerManager.addHandler(
this.handleReceivedFile, this.handleReceivedFile,
); );
this.fileTransferModel.readyToSendHandlerManager.addHandler(() =>
this.initiateTransfer(),
);
} }
} }
@@ -43,6 +43,7 @@ export default class NotificationViewModel {
(chat) => chat.chatModel.info.primaryChannel == notification.chat, (chat) => chat.chatModel.info.primaryChannel == notification.chat,
); );
chat.open(); chat.open();
chat.selectedPage.value = ChatPageType.Messages;
}; };
// loop // loop
+8 -4
View File
@@ -121,8 +121,12 @@ export default class BoardViewModel extends TaskContainingPageViewModel {
searchTerm, searchTerm,
]; ];
this.storageModel.write(suggestionPath, ""); this.storageModel.write(suggestionPath, "");
if (!this.coreViewModel.boardSearchSuggestions.value.has(searchTerm)) { if (
this.coreViewModel.boardSearchSuggestions.add(searchTerm); !this.coreViewModel.boardFilterStringSuggestions.value.has(
searchTerm,
)
) {
this.coreViewModel.boardFilterStringSuggestions.add(searchTerm);
} }
const lastSearchPath: string[] = this.getLastSearchPath(); const lastSearchPath: string[] = this.getLastSearchPath();
@@ -221,7 +225,7 @@ export default class BoardViewModel extends TaskContainingPageViewModel {
loadSearchSuggestions = (): void => { loadSearchSuggestions = (): void => {
const dirPath: string[] = this.getPreviousSearchesPath(); const dirPath: string[] = this.getPreviousSearchesPath();
const searches: string[] = this.storageModel.list(dirPath); const searches: string[] = this.storageModel.list(dirPath);
this.coreViewModel.boardSearchSuggestions.add(...searches); this.coreViewModel.boardFilterStringSuggestions.add(...searches);
}; };
restoreSearch = (): void => { restoreSearch = (): void => {
@@ -290,7 +294,7 @@ export default class BoardViewModel extends TaskContainingPageViewModel {
this.taskViewModels, this.taskViewModels,
this.filteredTaskViewModels, this.filteredTaskViewModels,
TaskViewModel.getStringsForFilter, TaskViewModel.getStringsForFilter,
this.coreViewModel.boardSearchSuggestions, this.coreViewModel.boardFilterStringSuggestions,
); );
this.searchViewModel.appliedQuery.subscribeSilent((newQuery) => { this.searchViewModel.appliedQuery.subscribeSilent((newQuery) => {
this.handleNewSearch(newQuery); this.handleNewSearch(newQuery);
+2
View File
@@ -164,6 +164,8 @@ export default class TaskPageViewModel {
this.chatViewModel = chatViewModel; this.chatViewModel = chatViewModel;
this.loadData();
// handlers // handlers
boardModel.boardHandlerManager.addHandler( boardModel.boardHandlerManager.addHandler(
(boardInfoFileContent: BoardInfoFileContent) => { (boardInfoFileContent: BoardInfoFileContent) => {
+2 -2
View File
@@ -101,7 +101,8 @@ export default class TaskViewModel {
this.loadTaskData(); this.loadTaskData();
}; };
closeAndSave = (): void => { closeAndSave = (e: Event): void => {
e.preventDefault();
this.close(); this.close();
this.save(); this.save();
}; };
@@ -234,7 +235,6 @@ export default class TaskViewModel {
static getStringsForFilter = (taskViewModel: TaskViewModel): string[] => { static getStringsForFilter = (taskViewModel: TaskViewModel): string[] => {
return [ return [
taskViewModel.task.name, taskViewModel.task.name,
taskViewModel.task.description ?? "",
taskViewModel.task.category ?? "", taskViewModel.task.category ?? "",
taskViewModel.task.status ?? "", taskViewModel.task.status ?? "",
taskViewModel.task.priority ?? "", taskViewModel.task.priority ?? "",