add keystroke hints

This commit is contained in:
marlon-erler
2026-09-29 22:24:34 +02:00
parent 7a532bbf5c
commit d3f3a1db21
25 changed files with 494 additions and 266 deletions
+24
View File
@@ -253,6 +253,30 @@ body[theme=dark] #background-wrapper #grass-2 {
transform-origin: center;
padding: var(--content-padding);
}
[ctkeystroke] {
position: relative;
}
[ctkeystroke]::after {
content: attr(ctkeystroke);
background: var(--primary);
color: var(--text-on-color);
--size: 24px;
position: absolute;
top: calc(50% - var(--size) / 2);
left: calc(50% - var(--size) / 2);
width: var(--size);
height: var(--size);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transform: translateY(10px);
transition: all calc(var(--animation-duration) / 2);
}
body[keystroke-active] [ctkeystroke]::after {
opacity: 1;
transform: translateY(0px);
}
/* src/View/homePage.css */
#home-page > div {
+345 -253
View File
@@ -1453,6 +1453,7 @@
if (!(e instanceof KeyboardEvent))
return console.trace("NOT A KEY EVENT");
if (_CoreViewModel.checkIsKeystroke(e) == false) return;
document.body.setAttribute("keystroke-active", "");
e.preventDefault();
const contexts = this.contexts;
while (contexts.length > 0) {
@@ -1462,6 +1463,9 @@
if (isHandled == true) break;
}
};
this.handleKeyUp = () => {
document.body.removeAttribute("keystroke-active");
};
// CHRON
this.chronHandlerManager = new HandlerManager();
this.todayDate = new State(/* @__PURE__ */ new Date());
@@ -1519,6 +1523,7 @@
this.updateText.value = this.translations.homePage.updateButton(latestVersion);
});
document.body.addEventListener("keydown", this.handleKeyDown);
document.body.addEventListener("keyup", this.handleKeyUp);
window.onpopstate = () => {
if (!this.context) return;
this.closeContext(this.context.contextId, true);
@@ -1610,6 +1615,18 @@
}
};
// src/View/keystrokes.ts
function getKeySymbol(keystroke) {
switch (keystroke) {
case "backspace":
return "\u232B";
case "enter":
return "\u23CE";
default:
return keystroke;
}
}
// src/ViewModel/Pages/homeViewModel.ts
var HomeViewModel = class extends Context {
constructor(coreViewModel2, settingsViewModel2, fileTransferViewModel2, storageViewModel2, connectionViewModel2) {
@@ -2212,6 +2229,47 @@
baseTheme: "black" /* Black */
};
// src/ViewModel/Global/onboardingViewModel.ts
var OnboardingViewModel = class {
// init
constructor(connectionViewmodel, fileTransferViewModel2, settingsViewModel2) {
this.connectionViewmodel = connectionViewmodel;
this.fileTransferViewModel = fileTransferViewModel2;
this.settingsViewModel = settingsViewModel2;
// state
this.presentedModal = new State(void 0);
// guards
this.cannotTransfer = createProxyState(
[this.connectionViewmodel.isConnected],
() => !this.connectionViewmodel.isConnected.value
);
// navigation
this.open = () => {
this.presentedModal.value = 0 /* Connection */;
};
this.showTransferOption = () => {
this.presentedModal.value = 1 /* TransferOrNew */;
};
this.setupNew = () => {
this.presentedModal.value = 2 /* Name */;
};
this.showTransferData = () => {
this.presentedModal.value = 3 /* Transfer */;
};
// methods
this.transferData = () => {
this.fileTransferViewModel.exitReception = () => this.showTransferData();
this.fileTransferViewModel.prepareReceivingData();
this.presentedModal.value = void 0;
};
this.finish = () => {
this.settingsViewModel.setName();
this.presentedModal.value = void 0;
};
if (this.settingsViewModel.settingsModel.username == "") this.open();
}
};
// src/ViewModel/Global/fileTransferViewModel.ts
var FileTransferViewModel = class extends Context {
// init
@@ -5055,7 +5113,7 @@
this.resetColor();
this.loadInfo();
this.subscribeReadStatus();
this.registerKeyStroke(" " /* Home */, this.close);
this.registerKeyStroke("w" /* Home */, this.close);
this.registerKeyStroke(
"u",
() => this.openPage("messages" /* Messages */)
@@ -5099,7 +5157,8 @@
this.showNotification = (message) => {
if (this.seenMessageIds.has(message.fileId)) return;
if (this.chatListViewModel.selectedChat.value == void 0) return;
if (message.senderId == this.settingsViewModel.settingsModel.userid) return;
if (message.senderId == this.settingsViewModel.settingsModel.userid)
return;
const notification = this.createNotification(message);
const currentChat = this.chatListViewModel.selectedChat.value.chatModel.id;
const currentPage = this.chatListViewModel.selectedChat.value.selectedPage.value;
@@ -5241,7 +5300,10 @@
}
return fullChannel;
};
this.notificationViewModel = new NotificationViewModel(this, this.settingsViewModel);
this.notificationViewModel = new NotificationViewModel(
this,
this.settingsViewModel
);
this.loadChats();
}
};
@@ -5261,8 +5323,17 @@
};
// src/View/Components/homePageButton.tsx
function HomePageButton(action, label, icon) {
return /* @__PURE__ */ createElement("button", { class: "tile flex-no", "on:click": action }, /* @__PURE__ */ createElement("span", { class: "icon" }, icon), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, label)));
function HomePageButton(action, label, icon, key) {
return /* @__PURE__ */ createElement(
"button",
{
class: "tile flex-no",
"on:click": action,
ctkeystroke: key
},
/* @__PURE__ */ createElement("span", { class: "icon" }, icon),
/* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, label))
);
}
// src/View/Components/chatEntry.tsx
@@ -5325,7 +5396,8 @@
class: "danger flex justify-center",
"aria-label": coreViewModel2.translations.homePage.disconnectAudioLabel,
"on:click": connectionViewModel2.disconnect,
"toggle:disabled": connectionViewModel2.cannotDisonnect
"toggle:disabled": connectionViewModel2.cannotDisonnect,
ctkeystroke: "x"
},
/* @__PURE__ */ createElement("span", { class: "icon" }, "link_off")
), /* @__PURE__ */ createElement(
@@ -5343,21 +5415,25 @@
class: "primary flex justify-center",
"aria-label": coreViewModel2.translations.homePage.connectAudioLabel,
"on:click": connectionViewModel2.connect,
"toggle:disabled": connectionViewModel2.cannotConnect
"toggle:disabled": connectionViewModel2.cannotConnect,
ctkeystroke: "c"
},
/* @__PURE__ */ createElement("span", { class: "icon" }, "link")
)), /* @__PURE__ */ createElement("hr", null), HomePageButton(
settingsViewModel2.showSettingsModal,
coreViewModel2.translations.homePage.settingsButton,
"settings"
"settings",
","
), HomePageButton(
fileTransferViewModel2.showDirectionSelectionModal,
coreViewModel2.translations.homePage.transferDataButton,
"sync_alt"
"sync_alt",
"t"
), HomePageButton(
storageViewModel2.showStorageModal,
coreViewModel2.translations.homePage.manageStorageButton,
"hard_drive"
"hard_drive",
"e"
), /* @__PURE__ */ createElement(
"button",
{
@@ -5402,7 +5478,7 @@
}
// src/View/Components/ribbonButton.tsx
function RibbonButton(label, icon, isSelected, select, isHighlighted = new State(false)) {
function RibbonButton(label, icon, isSelected, select, isHighlighted = new State(false), key) {
return /* @__PURE__ */ createElement(
"button",
{
@@ -5410,14 +5486,15 @@
"aria-label": label,
"toggle:selected": isSelected,
"toggle:highlight": isHighlighted,
"on:click": select
"on:click": select,
ctkeystroke: key
},
/* @__PURE__ */ createElement("span", { class: "icon" }, icon)
);
}
// src/View/Components/chatViewToggleButton.tsx
function ChatViewToggleButton(label, icon, page, chatViewModel) {
function ChatViewToggleButton(label, icon, page, chatViewModel, key) {
function select() {
chatViewModel.openPage(page);
}
@@ -5431,7 +5508,7 @@
(hasUnreadMessages) => isHighlighted.value = hasUnreadMessages
);
}
return RibbonButton(label, icon, isSelected, select, isHighlighted);
return RibbonButton(label, icon, isSelected, select, isHighlighted, key);
}
// src/View/Components/taskEntry.tsx
@@ -6008,14 +6085,16 @@
"button",
{
class: "flex",
"on:click": taskViewModel.closeAndDiscard
"on:click": taskViewModel.closeAndDiscard,
ctkeystroke: getKeySymbol("backspace" /* CloseOrCancel */)
},
coreViewModel2.translations.general.closeButton
), /* @__PURE__ */ createElement(
"button",
{
class: "flex primary",
"on:click": taskViewModel.closeAndSave
"on:click": taskViewModel.closeAndSave,
ctkeystroke: getKeySymbol("enter" /* Apply */)
},
coreViewModel2.translations.general.saveButton,
/* @__PURE__ */ createElement("span", { class: "icon" }, "save")
@@ -6072,7 +6151,8 @@
class: "standard",
"aria-label": coreViewModel2.translations.general.searchButtonClearAudioLabel,
"on:click": searchViewModel.clear,
"toggle:disabled": searchViewModel.cannotClear
"toggle:disabled": searchViewModel.cannotClear,
ctkeystroke: getKeySymbol("-" /* Reset */)
},
/* @__PURE__ */ createElement("span", { class: "icon" }, "close")
), /* @__PURE__ */ createElement(
@@ -6097,7 +6177,15 @@
)
]
}
))), /* @__PURE__ */ createElement("button", { "on:click": close }, coreViewModel2.translations.general.closeButton, /* @__PURE__ */ createElement("span", { class: "icon" }, "close"))));
))), /* @__PURE__ */ createElement(
"button",
{
"on:click": close,
ctkeystroke: getKeySymbol("backspace" /* CloseOrCancel */)
},
coreViewModel2.translations.general.closeButton,
/* @__PURE__ */ createElement("span", { class: "icon" }, "close")
)));
}
function SuggestionView(suggestion, searchViewModel, coreViewModel2) {
const isApplied = createProxyState(
@@ -6173,12 +6261,20 @@
coreViewModel2.translations.chatPage.task.deleteBoardButton,
"delete_forever",
boardViewModel.deleteBoard
))), /* @__PURE__ */ createElement("button", { "on:click": boardViewModel.hideSettings }, coreViewModel2.translations.general.closeButton, /* @__PURE__ */ createElement("span", { class: "icon" }, "close")))
))), /* @__PURE__ */ createElement(
"button",
{
"on:click": boardViewModel.hideSettings,
ctkeystroke: getKeySymbol("enter" /* Apply */)
},
coreViewModel2.translations.general.closeButton,
/* @__PURE__ */ createElement("span", { class: "icon" }, "close")
))
);
}
// src/View/Components/boardViewToggleButton.tsx
function BoardViewToggleButton(label, icon, page, boardViewModel) {
function BoardViewToggleButton(label, icon, page, boardViewModel, key) {
function select() {
boardViewModel.selectedPage.value = page;
}
@@ -6186,7 +6282,7 @@
[boardViewModel.selectedPage],
() => boardViewModel.selectedPage.value == page
);
return RibbonButton(label, icon, isSelected, select);
return RibbonButton(label, icon, isSelected, select, void 0, key);
}
// src/View/ChatPages/boardPage.tsx
@@ -6254,7 +6350,8 @@
class: "ghost board-toggle-button inset-outline",
"aria-label": coreViewModel2.translations.chatPage.task.toggleBoardButtonAudioLabel,
"on:click": boardViewModel.taskPageViewModel.toggleBoardList,
"toggle:selected": boardViewModel.taskPageViewModel.isShowingBoadList
"toggle:selected": boardViewModel.taskPageViewModel.isShowingBoadList,
ctkeystroke: getKeySymbol("." /* Options */)
},
/* @__PURE__ */ createElement("span", { class: "icon" }, "dock_to_right")
), /* @__PURE__ */ createElement(
@@ -6262,31 +6359,36 @@
{
class: "ghost",
"aria-label": coreViewModel2.translations.chatPage.task.boardSettingsHeadline,
"on:click": boardViewModel.showSettings
"on:click": boardViewModel.showSettings,
ctkeystroke: getKeySymbol("," /* Settings */)
},
/* @__PURE__ */ createElement("span", { class: "icon" }, "settings")
)), /* @__PURE__ */ createElement("span", { class: "scroll-h ribbon" }, BoardViewToggleButton(
coreViewModel2.translations.chatPage.task.listViewButtonAudioLabel,
"view_list",
"list" /* List */,
boardViewModel
boardViewModel,
"j"
), BoardViewToggleButton(
coreViewModel2.translations.chatPage.task.kanbanViewButtonAudioLabel,
"view_kanban",
"kanban" /* Kanban */,
boardViewModel
boardViewModel,
"k"
), BoardViewToggleButton(
coreViewModel2.translations.chatPage.task.statusViewButtonAudioLabel,
"grid_view",
"status-grid" /* StatusGrid */,
boardViewModel
boardViewModel,
"l"
)), /* @__PURE__ */ createElement("span", null, /* @__PURE__ */ createElement(
"button",
{
class: "ghost inset-outline",
"aria-label": coreViewModel2.translations.chatPage.task.filterTasksButtonAudioLabel,
"on:click": boardViewModel.showFilterModal,
"toggle:selected": boardViewModel.isFilterActive
"toggle:selected": boardViewModel.isFilterActive,
ctkeystroke: "=" /* Filter */
},
/* @__PURE__ */ createElement("span", { class: "icon" }, "filter_alt")
), /* @__PURE__ */ createElement(
@@ -6294,7 +6396,8 @@
{
class: "ghost",
"aria-label": coreViewModel2.translations.chatPage.task.createTaskButtonAudioLabel,
"on:click": boardViewModel.createTask
"on:click": boardViewModel.createTask,
ctkeystroke: getKeySymbol("a" /* Create */)
},
/* @__PURE__ */ createElement("span", { class: "icon" }, "add")
))), wrapper, BoardSettingsModal(coreViewModel2, boardViewModel), SearchModal(
@@ -6604,7 +6707,15 @@
), MessageReactionFilterButton(
messagePageViewModel,
"\u2753" /* Question */
)))), /* @__PURE__ */ createElement("button", { "on:click": messagePageViewModel.hideFilterModal }, coreViewModel2.translations.general.closeButton, /* @__PURE__ */ createElement("span", { class: "icon" }, "close"))));
)))), /* @__PURE__ */ createElement(
"button",
{
"on:click": messagePageViewModel.hideFilterModal,
ctkeystroke: getKeySymbol("backspace" /* CloseOrCancel */)
},
coreViewModel2.translations.general.closeButton,
/* @__PURE__ */ createElement("span", { class: "icon" }, "close")
)));
}
// src/View/Components/replyPreview.tsx
@@ -6626,7 +6737,8 @@
{
class: "standard square blur",
"on:click": chatMessageViewModel.cancelReply,
"aria-label": coreViewModel2.translations.chatPage.message.cancelReplyAudioLabel
"aria-label": coreViewModel2.translations.chatPage.message.cancelReplyAudioLabel,
ctkeystroke: getKeySymbol("backspace" /* CloseOrCancel */)
},
/* @__PURE__ */ createElement("span", { class: "icon" }, "close")
));
@@ -6972,7 +7084,8 @@
class: "ghost inset-outline",
"on:click": messagePageViewModel.showFilterModal,
"aria-label": coreViewModel2.translations.chatPage.message.filterMessagesButtonAudioLabel,
"toggle:selected": messagePageViewModel.isFilterActive
"toggle:selected": messagePageViewModel.isFilterActive,
ctkeystroke: getKeySymbol("=" /* Filter */)
},
/* @__PURE__ */ createElement("span", { class: "icon" }, "filter_alt")
))), /* @__PURE__ */ createElement("div", { class: "content" }, messageContainer, /* @__PURE__ */ createElement("div", { id: "composer" }, /* @__PURE__ */ createElement("div", { class: "content-width-constraint" }, /* @__PURE__ */ createElement(
@@ -7169,7 +7282,8 @@
{
class: "ghost",
"aria-label": coreViewModel2.translations.chatPage.calendar.todayButtonAudioLabel,
"on:click": calendarPageViewModel.showToday
"on:click": calendarPageViewModel.showToday,
ctkeystroke: getKeySymbol("-" /* Reset */)
},
/* @__PURE__ */ createElement("span", { class: "icon" }, "today")
)), /* @__PURE__ */ createElement("span", null, /* @__PURE__ */ createElement(
@@ -7177,7 +7291,8 @@
{
class: "ghost",
"aria-label": coreViewModel2.translations.chatPage.calendar.previousMonthButtonAudioLabel,
"on:click": calendarPageViewModel.showPreviousMonth
"on:click": calendarPageViewModel.showPreviousMonth,
ctkeystroke: "k"
},
/* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_back")
), /* @__PURE__ */ createElement("span", { class: "input-wrapper" }, /* @__PURE__ */ createElement(
@@ -7203,7 +7318,8 @@
{
class: "ghost",
"aria-label": coreViewModel2.translations.chatPage.calendar.nextMonthButtonAudioLabel,
"on:click": calendarPageViewModel.showNextMonth
"on:click": calendarPageViewModel.showNextMonth,
ctkeystroke: "l"
},
/* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward")
)), /* @__PURE__ */ createElement("span", null, /* @__PURE__ */ createElement(
@@ -7211,7 +7327,8 @@
{
class: "ghost",
"aria-label": coreViewModel2.translations.chatPage.task.createTaskButtonAudioLabel,
"on:click": calendarPageViewModel.createEvent
"on:click": calendarPageViewModel.createEvent,
ctkeystroke: getKeySymbol("a" /* Create */)
},
/* @__PURE__ */ createElement("span", { class: "icon" }, "add")
))), /* @__PURE__ */ createElement(
@@ -7298,7 +7415,8 @@
class: "ghost",
id: "close-button",
"aria-label": coreViewModel2.translations.chatPage.closeChatAudioLabe,
"on:click": chatViewModel.close
"on:click": chatViewModel.close,
ctkeystroke: getKeySymbol("w" /* Home */)
},
/* @__PURE__ */ createElement("span", { class: "icon" }, "close")
), /* @__PURE__ */ createElement(
@@ -7315,22 +7433,26 @@
coreViewModel2.translations.chatPage.pages.calendar,
"calendar_month",
"calendar" /* Calendar */,
chatViewModel
chatViewModel,
"o"
), ChatViewToggleButton(
coreViewModel2.translations.chatPage.pages.tasks,
"task_alt",
"tasks" /* Tasks */,
chatViewModel
chatViewModel,
"i"
), ChatViewToggleButton(
coreViewModel2.translations.chatPage.pages.messages,
"forum",
"messages" /* Messages */,
chatViewModel
chatViewModel,
"u"
), ChatViewToggleButton(
coreViewModel2.translations.chatPage.pages.settings,
"settings",
"settings" /* Settings */,
chatViewModel
chatViewModel,
getKeySymbol("," /* Settings */)
))), /* @__PURE__ */ createElement(
"div",
{
@@ -7510,7 +7632,15 @@
new State(DirectoryItemList(storageViewModel2)),
detailView,
true
)), /* @__PURE__ */ createElement("button", { "on:click": storageViewModel2.close }, coreViewModel2.translations.general.closeButton, /* @__PURE__ */ createElement("span", { class: "icon" }, "close"))));
)), /* @__PURE__ */ createElement(
"button",
{
"on:click": storageViewModel2.close,
ctkeystroke: getKeySymbol("backspace" /* CloseOrCancel */)
},
coreViewModel2.translations.general.closeButton,
/* @__PURE__ */ createElement("span", { class: "icon" }, "close")
)));
}
// src/View/Components/optionButton.tsx
@@ -7598,7 +7728,15 @@
detailView,
true,
settingsViewModel2.selectedModalPage
)), /* @__PURE__ */ createElement("button", { "on:click": settingsViewModel2.close }, coreViewModel2.translations.general.closeButton, /* @__PURE__ */ createElement("span", { class: "icon" }, "close")))
)), /* @__PURE__ */ createElement(
"button",
{
"on:click": settingsViewModel2.close,
ctkeystroke: getKeySymbol("backspace" /* CloseOrCancel */)
},
coreViewModel2.translations.general.closeButton,
/* @__PURE__ */ createElement("span", { class: "icon" }, "close")
))
);
}
function SettingsLeftPane(coreViewModel2, settingsViewModel2) {
@@ -7712,6 +7850,146 @@
));
}
// src/View/Modals/onboardingModal.tsx
function OnboardingModalWrapper(coreViewModel2, onboardingViewModel2) {
return /* @__PURE__ */ createElement("div", null, ConnectionModal(coreViewModel2, onboardingViewModel2), TransferModal(coreViewModel2, onboardingViewModel2), NameModal(coreViewModel2, onboardingViewModel2), TransferDataModal(coreViewModel2, onboardingViewModel2));
}
function ConnectionModal(coreViewModel2, onboardingViewModel2) {
const isPresented = createProxyState(
[onboardingViewModel2.presentedModal],
() => onboardingViewModel2.presentedModal.value == 0 /* Connection */
);
const connectionViewModel2 = onboardingViewModel2.connectionViewmodel;
const nextButton = createProxyState(
[connectionViewModel2.isConnected],
() => coreViewModel2.translations.onboarding.connectionNextButton(
connectionViewModel2.isConnected.value
)
);
return /* @__PURE__ */ createElement("div", { class: "modal", "toggle:open": isPresented }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, coreViewModel2.translations.onboarding.connectionHeadline), /* @__PURE__ */ createElement("p", { class: "secondary width-input" }, coreViewModel2.translations.onboarding.connectionDescription), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("label", { class: "tile flex-no" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "cell_tower"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, coreViewModel2.translations.homePage.serverAddress), /* @__PURE__ */ createElement(
"input",
{
placeholder: coreViewModel2.translations.homePage.serverAddressPlaceholder,
"bind:value": connectionViewModel2.serverAddressInput,
"on:enter": connectionViewModel2.connect
}
))), /* @__PURE__ */ createElement("div", { class: "flex-row width-input justify-end" }, /* @__PURE__ */ createElement(
"button",
{
class: "standard width-50",
"on:click": connectionViewModel2.connect,
"toggle:disabled": connectionViewModel2.cannotConnect
},
coreViewModel2.translations.onboarding.connectButton
))), /* @__PURE__ */ createElement("div", { class: "flex-row justify-end" }, /* @__PURE__ */ createElement(
"button",
{
class: "primary width-50",
"on:click": onboardingViewModel2.showTransferOption
},
/* @__PURE__ */ createElement("span", { "subscribe:innerText": nextButton }),
/* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward")
))));
}
function TransferModal(coreViewModel2, onboardingViewModel2) {
const isPresented = createProxyState(
[onboardingViewModel2.presentedModal],
() => onboardingViewModel2.presentedModal.value == 1 /* TransferOrNew */
);
return /* @__PURE__ */ createElement("div", { class: "modal", "toggle:open": isPresented }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, coreViewModel2.translations.onboarding.transferOptionsHeadline), /* @__PURE__ */ createElement("p", { class: "secondary width-input" }, coreViewModel2.translations.onboarding.transferOptionsDescription), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("div", { class: "flex-column gap" }, /* @__PURE__ */ createElement(
"button",
{
class: "tile",
"on:click": onboardingViewModel2.showTransferData,
"toggle:disabled": onboardingViewModel2.cannotTransfer
},
/* @__PURE__ */ createElement("div", null, coreViewModel2.translations.onboarding.transferOptionTransfer),
/* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward")
), /* @__PURE__ */ createElement(
"button",
{
class: "tile",
"on:click": onboardingViewModel2.setupNew
},
/* @__PURE__ */ createElement("div", null, coreViewModel2.translations.onboarding.transferOptionNew),
/* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward")
))), /* @__PURE__ */ createElement("div", { class: "flex-row" }, /* @__PURE__ */ createElement(
"button",
{
class: "standard width-50",
"on:click": onboardingViewModel2.open
},
coreViewModel2.translations.general.backButton
))));
}
function NameModal(coreViewModel2, onboardingViewModel2) {
const isPresented = createProxyState(
[onboardingViewModel2.presentedModal],
() => onboardingViewModel2.presentedModal.value == 2 /* Name */
);
const settingsViewModel2 = onboardingViewModel2.settingsViewModel;
return /* @__PURE__ */ createElement("div", { class: "modal", "toggle:open": isPresented }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, coreViewModel2.translations.onboarding.nameHeadline), /* @__PURE__ */ createElement("p", { class: "secondary width-input" }, coreViewModel2.translations.onboarding.nameDescription), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("label", { class: "tile flex-no" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "account_circle"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, coreViewModel2.translations.settings.account.yourNameLabel), /* @__PURE__ */ createElement(
"input",
{
placeholder: coreViewModel2.translations.settings.account.yourNamePlaceholder,
"bind:value": settingsViewModel2.usernameInput
}
)))), /* @__PURE__ */ createElement("div", { class: "flex-row" }, /* @__PURE__ */ createElement(
"button",
{
class: "standard width-50",
"on:click": onboardingViewModel2.showTransferOption
},
coreViewModel2.translations.general.backButton
), /* @__PURE__ */ createElement(
"button",
{
class: "primary width-50",
"on:click": onboardingViewModel2.finish
},
coreViewModel2.translations.general.setButton,
/* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward")
))));
}
function TransferDataModal(coreViewModel2, onboardingViewModel2) {
const isPresented = createProxyState(
[onboardingViewModel2.presentedModal],
() => onboardingViewModel2.presentedModal.value == 3 /* Transfer */
);
const fileTransferViewModel2 = onboardingViewModel2.fileTransferViewModel;
return /* @__PURE__ */ createElement("div", { class: "modal", "toggle:open": isPresented }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, coreViewModel2.translations.onboarding.transferHeadline), /* @__PURE__ */ createElement("p", { class: "secondary width-input" }, coreViewModel2.translations.onboarding.transferDescription), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("div", { class: "flex-column gap content-margin-bottom" }, /* @__PURE__ */ createElement("label", { class: "tile" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "forum"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", { class: "secondary" }, coreViewModel2.translations.dataTransferModal.transferChannelHeadline), /* @__PURE__ */ createElement(
"input",
{
type: "number",
"on:enter": fileTransferViewModel2.prepareReceivingData,
"bind:value": fileTransferViewModel2.receivingTransferChannel
}
))), /* @__PURE__ */ createElement("label", { class: "tile" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "key"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", { class: "secondary" }, coreViewModel2.translations.dataTransferModal.transferKeyHeadline), /* @__PURE__ */ createElement(
"input",
{
type: "number",
"on:enter": fileTransferViewModel2.prepareReceivingData,
"bind:value": fileTransferViewModel2.receivingTransferKey
}
))))), /* @__PURE__ */ createElement("div", { class: "flex-row" }, /* @__PURE__ */ createElement(
"button",
{
class: "standard width-50",
"on:click": onboardingViewModel2.showTransferOption,
"toggle:disabled": fileTransferViewModel2.cannotExitReception
},
coreViewModel2.translations.general.backButton
), /* @__PURE__ */ createElement(
"button",
{
class: "primary width-50",
"on:click": onboardingViewModel2.transferData
},
coreViewModel2.translations.onboarding.transferButton,
/* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward")
))));
}
// src/View/Components/textSpan.tsx
var StringToTextSpan = (string) => {
return /* @__PURE__ */ createElement("span", { class: "ellipsis" }, string);
@@ -7740,7 +8018,15 @@
function toggle() {
isSelected.value = !isSelected.value;
}
return /* @__PURE__ */ createElement("button", { class: "tile", "toggle:selected": isSelected, "on:click": toggle }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("b", { class: "ellipsis" }, fileOption.label), /* @__PURE__ */ createElement("span", { class: "secondary ellipsis" }, StorageModel.pathComponentsToString(...fileOption.path))));
return /* @__PURE__ */ createElement(
"button",
{
class: "tile",
"toggle:selected": isSelected,
"on:click": toggle
},
/* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("b", { class: "ellipsis" }, fileOption.label), /* @__PURE__ */ createElement("span", { class: "secondary ellipsis" }, StorageModel.pathComponentsToString(...fileOption.path)))
);
}
function DirectionSelectionModal(coreViewModel2, connectionViewModel2, fileTransferViewModel2) {
const isPresented = createProxyState(
@@ -7789,7 +8075,15 @@
/* @__PURE__ */ createElement("span", { class: "icon" }, "upload_file"),
/* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("b", null, coreViewModel2.translations.dataTransferModal.importButton)),
/* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward")
))), /* @__PURE__ */ createElement("button", { "on:click": fileTransferViewModel2.close }, coreViewModel2.translations.general.closeButton, /* @__PURE__ */ createElement("span", { class: "icon" }, "close"))));
))), /* @__PURE__ */ createElement(
"button",
{
"on:click": fileTransferViewModel2.close,
ctkeystroke: getKeySymbol("backspace" /* CloseOrCancel */)
},
coreViewModel2.translations.general.closeButton,
/* @__PURE__ */ createElement("span", { class: "icon" }, "close")
)));
}
function FileSelectionModal(coreViewModel2, fileTransferViewModel2) {
const OptionConverter = (fileOption) => {
@@ -8132,7 +8426,7 @@
}
// src/View/Modals/connectionModal.tsx
function ConnectionModal(coreViewModel2, connectionViewModel2) {
function ConnectionModal2(coreViewModel2, connectionViewModel2) {
const previousAddressConverter = (address) => {
function connnect() {
connectionViewModel2.connectToAddress(address);
@@ -8770,212 +9064,6 @@
}
};
// src/ViewModel/Global/onboardingViewModel.ts
var OnboardingViewModel = class {
// init
constructor(connectionViewmodel, fileTransferViewModel2, settingsViewModel2) {
this.connectionViewmodel = connectionViewmodel;
this.fileTransferViewModel = fileTransferViewModel2;
this.settingsViewModel = settingsViewModel2;
// state
this.presentedModal = new State(void 0);
// guards
this.cannotTransfer = createProxyState([this.connectionViewmodel.isConnected], () => !this.connectionViewmodel.isConnected.value);
// navigation
this.open = () => {
this.presentedModal.value = 0 /* Connection */;
};
this.showTransferOption = () => {
this.presentedModal.value = 1 /* TransferOrNew */;
};
this.setupNew = () => {
this.presentedModal.value = 2 /* Name */;
};
this.showTransferData = () => {
this.presentedModal.value = 3 /* Transfer */;
};
// methods
this.transferData = () => {
this.fileTransferViewModel.exitReception = () => this.showTransferData();
this.fileTransferViewModel.prepareReceivingData();
this.presentedModal.value = void 0;
};
this.finish = () => {
this.settingsViewModel.setName();
this.presentedModal.value = void 0;
};
if (this.settingsViewModel.settingsModel.username == "") this.open();
}
};
// src/View/Modals/onboardingModal.tsx
function OnboardingModalWrapper(coreViewModel2, onboardingViewModel2) {
return /* @__PURE__ */ createElement("div", null, ConnectionModal2(coreViewModel2, onboardingViewModel2), TransferModal(coreViewModel2, onboardingViewModel2), NameModal(coreViewModel2, onboardingViewModel2), TransferDataModal(coreViewModel2, onboardingViewModel2));
}
function ConnectionModal2(coreViewModel2, onboardingViewModel2) {
const isPresented = createProxyState(
[onboardingViewModel2.presentedModal],
() => onboardingViewModel2.presentedModal.value == 0 /* Connection */
);
const connectionViewModel2 = onboardingViewModel2.connectionViewmodel;
const nextButton = createProxyState([connectionViewModel2.isConnected], () => coreViewModel2.translations.onboarding.connectionNextButton(connectionViewModel2.isConnected.value));
return /* @__PURE__ */ createElement(
"div",
{
class: "modal",
"toggle:open": isPresented
},
/* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, coreViewModel2.translations.onboarding.connectionHeadline), /* @__PURE__ */ createElement("p", { class: "secondary width-input" }, coreViewModel2.translations.onboarding.connectionDescription), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("label", { class: "tile flex-no" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "cell_tower"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, coreViewModel2.translations.homePage.serverAddress), /* @__PURE__ */ createElement(
"input",
{
placeholder: coreViewModel2.translations.homePage.serverAddressPlaceholder,
"bind:value": connectionViewModel2.serverAddressInput,
"on:enter": connectionViewModel2.connect
}
))), /* @__PURE__ */ createElement("div", { class: "flex-row width-input justify-end" }, /* @__PURE__ */ createElement(
"button",
{
class: "standard width-50",
"on:click": connectionViewModel2.connect,
"toggle:disabled": connectionViewModel2.cannotConnect
},
coreViewModel2.translations.onboarding.connectButton
))), /* @__PURE__ */ createElement("div", { class: "flex-row justify-end" }, /* @__PURE__ */ createElement(
"button",
{
class: "primary width-50",
"on:click": onboardingViewModel2.showTransferOption
},
/* @__PURE__ */ createElement(
"span",
{
"subscribe:innerText": nextButton
}
),
/* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward")
)))
);
}
function TransferModal(coreViewModel2, onboardingViewModel2) {
const isPresented = createProxyState(
[onboardingViewModel2.presentedModal],
() => onboardingViewModel2.presentedModal.value == 1 /* TransferOrNew */
);
return /* @__PURE__ */ createElement(
"div",
{
class: "modal",
"toggle:open": isPresented
},
/* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, coreViewModel2.translations.onboarding.transferOptionsHeadline), /* @__PURE__ */ createElement("p", { class: "secondary width-input" }, coreViewModel2.translations.onboarding.transferOptionsDescription), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("div", { class: "flex-column gap" }, /* @__PURE__ */ createElement(
"button",
{
class: "tile",
"on:click": onboardingViewModel2.showTransferData,
"toggle:disabled": onboardingViewModel2.cannotTransfer
},
/* @__PURE__ */ createElement("div", null, coreViewModel2.translations.onboarding.transferOptionTransfer),
/* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward")
), /* @__PURE__ */ createElement(
"button",
{
class: "tile",
"on:click": onboardingViewModel2.setupNew
},
/* @__PURE__ */ createElement("div", null, coreViewModel2.translations.onboarding.transferOptionNew),
/* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward")
))), /* @__PURE__ */ createElement("div", { class: "flex-row" }, /* @__PURE__ */ createElement(
"button",
{
class: "standard width-50",
"on:click": onboardingViewModel2.open
},
coreViewModel2.translations.general.backButton
)))
);
}
function NameModal(coreViewModel2, onboardingViewModel2) {
const isPresented = createProxyState(
[onboardingViewModel2.presentedModal],
() => onboardingViewModel2.presentedModal.value == 2 /* Name */
);
const settingsViewModel2 = onboardingViewModel2.settingsViewModel;
return /* @__PURE__ */ createElement(
"div",
{
class: "modal",
"toggle:open": isPresented
},
/* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, coreViewModel2.translations.onboarding.nameHeadline), /* @__PURE__ */ createElement("p", { class: "secondary width-input" }, coreViewModel2.translations.onboarding.nameDescription), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("label", { class: "tile flex-no" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "account_circle"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", null, coreViewModel2.translations.settings.account.yourNameLabel), /* @__PURE__ */ createElement(
"input",
{
placeholder: coreViewModel2.translations.settings.account.yourNamePlaceholder,
"bind:value": settingsViewModel2.usernameInput
}
)))), /* @__PURE__ */ createElement("div", { class: "flex-row" }, /* @__PURE__ */ createElement(
"button",
{
class: "standard width-50",
"on:click": onboardingViewModel2.showTransferOption
},
coreViewModel2.translations.general.backButton
), /* @__PURE__ */ createElement(
"button",
{
class: "primary width-50",
"on:click": onboardingViewModel2.finish
},
coreViewModel2.translations.general.setButton,
/* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward")
)))
);
}
function TransferDataModal(coreViewModel2, onboardingViewModel2) {
const isPresented = createProxyState(
[onboardingViewModel2.presentedModal],
() => onboardingViewModel2.presentedModal.value == 3 /* Transfer */
);
const fileTransferViewModel2 = onboardingViewModel2.fileTransferViewModel;
return /* @__PURE__ */ createElement(
"div",
{
class: "modal",
"toggle:open": isPresented
},
/* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, coreViewModel2.translations.onboarding.transferHeadline), /* @__PURE__ */ createElement("p", { class: "secondary width-input" }, coreViewModel2.translations.onboarding.transferDescription), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("div", { class: "flex-column gap content-margin-bottom" }, /* @__PURE__ */ createElement("label", { class: "tile" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "forum"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", { class: "secondary" }, coreViewModel2.translations.dataTransferModal.transferChannelHeadline), /* @__PURE__ */ createElement(
"input",
{
type: "number",
"on:enter": fileTransferViewModel2.prepareReceivingData,
"bind:value": fileTransferViewModel2.receivingTransferChannel
}
))), /* @__PURE__ */ createElement("label", { class: "tile" }, /* @__PURE__ */ createElement("span", { class: "icon" }, "key"), /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("span", { class: "secondary" }, coreViewModel2.translations.dataTransferModal.transferKeyHeadline), /* @__PURE__ */ createElement(
"input",
{
type: "number",
"on:enter": fileTransferViewModel2.prepareReceivingData,
"bind:value": fileTransferViewModel2.receivingTransferKey
}
))))), /* @__PURE__ */ createElement("div", { class: "flex-row" }, /* @__PURE__ */ createElement(
"button",
{
class: "standard width-50",
"on:click": onboardingViewModel2.showTransferOption,
"toggle:disabled": fileTransferViewModel2.cannotExitReception
},
coreViewModel2.translations.general.backButton
), /* @__PURE__ */ createElement(
"button",
{
class: "primary width-50",
"on:click": onboardingViewModel2.transferData
},
coreViewModel2.translations.onboarding.transferButton,
/* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward")
)))
);
}
// src/index.tsx
var storageModel = new StorageModel();
var settingsModel = new SettingsModel(storageModel);
@@ -9009,7 +9097,11 @@
contactListViewModel
);
var fileTransferViewModel = new FileTransferViewModel(coreViewModel);
var onboardingViewModel = new OnboardingViewModel(connectionViewModel, fileTransferViewModel, settingsViewModel);
var onboardingViewModel = new OnboardingViewModel(
connectionViewModel,
fileTransferViewModel,
settingsViewModel
);
var homeViewModel = new HomeViewModel(
coreViewModel,
settingsViewModel,
@@ -9037,7 +9129,7 @@
),
ChatPageWrapper(coreViewModel, chatListViewModel),
OnboardingModalWrapper(coreViewModel, onboardingViewModel),
ConnectionModal(coreViewModel, connectionViewModel),
ConnectionModal2(coreViewModel, connectionViewModel),
DataTransferModalWrapper(
coreViewModel,
connectionViewModel,
Vendored
+1 -1
View File
@@ -1,4 +1,4 @@
const VERSION = "2610 Beta 19"
const VERSION = "2610 Beta 20"
function processUrl(event) {
const url = event.request.url;
+1 -1
View File
@@ -1 +1 @@
2610 Beta 19
2610 Beta 20
+8
View File
@@ -1,6 +1,7 @@
import { BoardStatusGridPage } from "./boardStatusGridPage";
import { BoardKanbanPage } from "./boardKanbanPage";
import { ViewController } from "../viewController";
import { CommonKeys, getKeySymbol } from "../keystrokes";
import { TaskSettingsModal } from "../Modals/taskSettingsModal";
import { SearchModal } from "../Modals/searchModal";
import { BoardSettingsModal } from "../Modals/boardSettingsModal";
@@ -96,6 +97,7 @@ export function BoardPage(
toggle:selected={
boardViewModel.taskPageViewModel.isShowingBoadList
}
ctkeystroke={getKeySymbol(CommonKeys.Options)}
>
<span class="icon">dock_to_right</span>
</button>
@@ -106,6 +108,7 @@ export function BoardPage(
.boardSettingsHeadline
}
on:click={boardViewModel.showSettings}
ctkeystroke={getKeySymbol(CommonKeys.Settings)}
>
<span class="icon">settings</span>
</button>
@@ -117,6 +120,7 @@ export function BoardPage(
"view_list",
BoardPageTypes.List,
boardViewModel,
"j",
)}
{BoardViewToggleButton(
coreViewModel.translations.chatPage.task
@@ -124,6 +128,7 @@ export function BoardPage(
"view_kanban",
BoardPageTypes.Kanban,
boardViewModel,
"k",
)}
{BoardViewToggleButton(
coreViewModel.translations.chatPage.task
@@ -131,6 +136,7 @@ export function BoardPage(
"grid_view",
BoardPageTypes.StatusGrid,
boardViewModel,
"l",
)}
</span>
<span>
@@ -142,6 +148,7 @@ export function BoardPage(
}
on:click={boardViewModel.showFilterModal}
toggle:selected={boardViewModel.isFilterActive}
ctkeystroke={CommonKeys.Filter}
>
<span class="icon">filter_alt</span>
</button>
@@ -152,6 +159,7 @@ export function BoardPage(
.createTaskButtonAudioLabel
}
on:click={boardViewModel.createTask}
ctkeystroke={getKeySymbol(CommonKeys.Create)}
>
<span class="icon">add</span>
</button>
+5
View File
@@ -1,5 +1,6 @@
import "./calendarPage.css";
import { ViewController } from "../viewController";
import { CommonKeys, getKeySymbol } from "../keystrokes";
import { TaskSettingsModal } from "../Modals/taskSettingsModal";
import { TaskViewModelToEntry } from "../Components/taskEntry";
import { PlaceholderView } from "../Components/placeholderView";
@@ -115,6 +116,7 @@ export function CalendarPage(
.todayButtonAudioLabel
}
on:click={calendarPageViewModel.showToday}
ctkeystroke={getKeySymbol(CommonKeys.Reset)}
>
<span class="icon">today</span>
</button>
@@ -129,6 +131,7 @@ export function CalendarPage(
on:click={
calendarPageViewModel.showPreviousMonth
}
ctkeystroke="k"
>
<span class="icon">arrow_back</span>
</button>
@@ -171,6 +174,7 @@ export function CalendarPage(
.nextMonthButtonAudioLabel
}
on:click={calendarPageViewModel.showNextMonth}
ctkeystroke="l"
>
<span class="icon">arrow_forward</span>
</button>
@@ -183,6 +187,7 @@ export function CalendarPage(
.createTaskButtonAudioLabel
}
on:click={calendarPageViewModel.createEvent}
ctkeystroke={getKeySymbol(CommonKeys.Create)}
>
<span class="icon">add</span>
</button>
+2
View File
@@ -1,5 +1,6 @@
import "./messagePage.css";
import { ViewController } from "../viewController";
import { CommonKeys, getKeySymbol } from "../keystrokes";
import { MessageFilterModal } from "../Modals/messageFilterModal";
import { ReplyPreview } from "../Components/replyPreview";
import { ChatMessage } from "../Components/chatMessage";
@@ -129,6 +130,7 @@ export function MessagePage(
toggle:selected={
messagePageViewModel.isFilterActive
}
ctkeystroke={getKeySymbol(CommonKeys.Filter)}
>
<span class="icon">filter_alt</span>
</button>
@@ -9,6 +9,7 @@ export function BoardViewToggleButton(
icon: string,
page: BoardPageTypes,
boardViewModel: BoardViewModel,
key: string,
) {
function select() {
boardViewModel.selectedPage.value = page;
@@ -19,5 +20,5 @@ export function BoardViewToggleButton(
() => boardViewModel.selectedPage.value == page,
);
return RibbonButton(label, icon, isSelected, select);
return RibbonButton(label, icon, isSelected, select, undefined, key);
}
+2 -1
View File
@@ -9,6 +9,7 @@ export function ChatViewToggleButton(
icon: string,
page: ChatPageTypes,
chatViewModel: ChatViewModel,
key: string,
) {
function select() {
chatViewModel.openPage(page);
@@ -26,5 +27,5 @@ export function ChatViewToggleButton(
);
}
return RibbonButton(label, icon, isSelected, select, isHighlighted);
return RibbonButton(label, icon, isSelected, select, isHighlighted, key);
}
+2 -1
View File
@@ -4,9 +4,10 @@ export function HomePageButton(
action: () => void,
label: string,
icon: string,
key: string,
) {
return (
<button class="tile flex-no" on:click={action}>
<button class="tile flex-no" on:click={action} ctkeystroke={key}>
<span class="icon">{icon}</span>
<div>
<span>{label}</span>
+2
View File
@@ -1,3 +1,4 @@
import { CommonKeys, getKeySymbol } from "../keystrokes";
import * as React from "../../react";
import CoreViewModel from "../../ViewModel/Global/coreViewModel";
import ChatMessageViewModel from "../../ViewModel/Chat/chatMessageViewModel";
@@ -25,6 +26,7 @@ export function ReplyPreview(
coreViewModel.translations.chatPage.message
.cancelReplyAudioLabel
}
ctkeystroke={getKeySymbol(CommonKeys.CloseOrCancel)}
>
<span class="icon">close</span>
</button>
+2
View File
@@ -6,6 +6,7 @@ export function RibbonButton(
isSelected: React.State<boolean>,
select: () => void,
isHighlighted: React.State<boolean> = new React.State(false),
key: string,
) {
return (
<button
@@ -14,6 +15,7 @@ export function RibbonButton(
toggle:selected={isSelected}
toggle:highlight={isHighlighted}
on:click={select}
ctkeystroke={key}
>
<span class="icon">{icon}</span>
</button>
+5 -1
View File
@@ -1,4 +1,5 @@
import { ViewController } from "../viewController";
import { CommonKeys, getKeySymbol } from "../keystrokes";
import { DangerousActionButton } from "../Components/dangerousActionButton";
import { ColorPicker } from "../Components/colorPicker";
import * as React from "../../react";
@@ -60,7 +61,10 @@ export function BoardSettingsModal(
)}
</div>
</main>
<button on:click={boardViewModel.hideSettings}>
<button
on:click={boardViewModel.hideSettings}
ctkeystroke={getKeySymbol(CommonKeys.Apply)}
>
{coreViewModel.translations.general.closeButton}
<span class="icon">close</span>
</button>
+5 -1
View File
@@ -1,4 +1,5 @@
import { ViewController } from "../viewController";
import { CommonKeys, getKeySymbol } from "../keystrokes";
import { StringToTextSpan } from "../Components/textSpan";
import * as React from "../../react";
import FileTransferViewModel, {
@@ -172,7 +173,10 @@ function DirectionSelectionModal(
</button>
</div>
</main>
<button on:click={fileTransferViewModel.close}>
<button
on:click={fileTransferViewModel.close}
ctkeystroke={getKeySymbol(CommonKeys.CloseOrCancel)}
>
{coreViewModel.translations.general.closeButton}
<span class="icon">close</span>
</button>
+5 -1
View File
@@ -1,4 +1,5 @@
import { ViewController } from "../viewController";
import { CommonKeys, getKeySymbol } from "../keystrokes";
import { MessageReactionFilterButton } from "../Components/messageReactionFilterButton";
import * as React from "../../react";
import MessagePageViewModel from "../../ViewModel/Pages/messagePageViewModel";
@@ -112,7 +113,10 @@ export function MessageFilterModal<T>(
</div>
</div>
</main>
<button on:click={messagePageViewModel.hideFilterModal}>
<button
on:click={messagePageViewModel.hideFilterModal}
ctkeystroke={getKeySymbol(CommonKeys.CloseOrCancel)}
>
{coreViewModel.translations.general.closeButton}
<span class="icon">close</span>
</button>
+6 -1
View File
@@ -1,5 +1,6 @@
import { v4 } from "uuid";
import { ViewController } from "../viewController";
import { CommonKeys, getKeySymbol } from "../keystrokes";
import { StringToOption } from "../Components/option";
import { DeletableListItem } from "../Components/deletableListItem";
import * as React from "../../react";
@@ -55,6 +56,7 @@ export function SearchModal<T>(
}
on:click={searchViewModel.clear}
toggle:disabled={searchViewModel.cannotClear}
ctkeystroke={getKeySymbol(CommonKeys.Reset)}
>
<span class="icon">close</span>
</button>
@@ -93,7 +95,10 @@ export function SearchModal<T>(
></div>
</div>
</main>
<button on:click={close}>
<button
on:click={close}
ctkeystroke={getKeySymbol(CommonKeys.CloseOrCancel)}
>
{coreViewModel.translations.general.closeButton}
<span class="icon">close</span>
</button>
+5 -1
View File
@@ -1,5 +1,6 @@
import { SplitModal } from "./splitModal";
import { languageNames } from "../translations";
import { CommonKeys, getKeySymbol } from "../keystrokes";
import { PlaceholderView } from "../Components/placeholderView";
import { OptionButtonList } from "../Components/optionButtonList";
import { NavigationButton } from "../Components/navigationButton";
@@ -62,7 +63,10 @@ export function SettingsModal(
settingsViewModel.selectedModalPage,
)}
</main>
<button on:click={settingsViewModel.close}>
<button
on:click={settingsViewModel.close}
ctkeystroke={getKeySymbol(CommonKeys.CloseOrCancel)}
>
{coreViewModel.translations.general.closeButton}
<span class="icon">close</span>
</button>
+5 -1
View File
@@ -1,4 +1,5 @@
import { SplitModal } from "./splitModal";
import { CommonKeys, getKeySymbol } from "../keystrokes";
import { UsageBar } from "../Components/usageBar";
import { DirectoryItemList } from "../Components/directoryItemList";
import { DangerousActionButton } from "../Components/dangerousActionButton";
@@ -95,7 +96,10 @@ export function StorageModal(
true,
)}
</main>
<button on:click={storageViewModel.close}>
<button
on:click={storageViewModel.close}
ctkeystroke={getKeySymbol(CommonKeys.CloseOrCancel)}
>
{coreViewModel.translations.general.closeButton}
<span class="icon">close</span>
</button>
+3
View File
@@ -1,4 +1,5 @@
import { v4 } from "uuid";
import { CommonKeys, getKeySymbol } from "../keystrokes";
import {
Entry,
Option,
@@ -269,12 +270,14 @@ export function TaskSettingsModal(
<button
class="flex"
on:click={taskViewModel.closeAndDiscard}
ctkeystroke={getKeySymbol(CommonKeys.CloseOrCancel)}
>
{coreViewModel.translations.general.closeButton}
</button>
<button
class="flex primary"
on:click={taskViewModel.closeAndSave}
ctkeystroke={getKeySymbol(CommonKeys.Apply)}
>
{coreViewModel.translations.general.saveButton}
<span class="icon">save</span>
+6
View File
@@ -1,4 +1,5 @@
import { ViewController } from "./viewController";
import { CommonKeys, getKeySymbol } from "./keystrokes";
import "./homePage.css";
import { ChatViewToggleButton } from "./Components/chatViewToggleButton";
import { TaskPage } from "./ChatPages/taskPage";
@@ -80,6 +81,7 @@ export function ChatPage(
.closeChatAudioLabe
}
on:click={chatViewModel.close}
ctkeystroke={getKeySymbol(CommonKeys.Home)}
>
<span class="icon">close</span>
</button>
@@ -111,24 +113,28 @@ export function ChatPage(
"calendar_month",
ChatPageTypes.Calendar,
chatViewModel,
"o",
)}
{ChatViewToggleButton(
coreViewModel.translations.chatPage.pages.tasks,
"task_alt",
ChatPageTypes.Tasks,
chatViewModel,
"i",
)}
{ChatViewToggleButton(
coreViewModel.translations.chatPage.pages.messages,
"forum",
ChatPageTypes.Messages,
chatViewModel,
"u",
)}
{ChatViewToggleButton(
coreViewModel.translations.chatPage.pages.settings,
"settings",
ChatPageTypes.Settings,
chatViewModel,
getKeySymbol(CommonKeys.Settings),
)}
</span>
</div>
+5
View File
@@ -57,6 +57,7 @@ export function HomePage(
}
on:click={connectionViewModel.disconnect}
toggle:disabled={connectionViewModel.cannotDisonnect}
ctkeystroke="x"
>
<span class="icon">link_off</span>
</button>
@@ -80,6 +81,7 @@ export function HomePage(
}
on:click={connectionViewModel.connect}
toggle:disabled={connectionViewModel.cannotConnect}
ctkeystroke="c"
>
<span class="icon">link</span>
</button>
@@ -91,16 +93,19 @@ export function HomePage(
settingsViewModel.showSettingsModal,
coreViewModel.translations.homePage.settingsButton,
"settings",
",",
)}
{HomePageButton(
fileTransferViewModel.showDirectionSelectionModal,
coreViewModel.translations.homePage.transferDataButton,
"sync_alt",
"t",
)}
{HomePageButton(
storageViewModel.showStorageModal,
coreViewModel.translations.homePage.manageStorageButton,
"hard_drive",
"e",
)}
<button
+12 -1
View File
@@ -1,5 +1,5 @@
export enum CommonKeys {
Home = " ",
Home = "w",
Filter = "=",
Reset = "-",
Options = ".",
@@ -8,3 +8,14 @@ export enum CommonKeys {
Settings = ",",
Create = "a",
}
export function getKeySymbol(keystroke: string): string {
switch (keystroke) {
case "backspace":
return "⌫";
case "enter":
return "⏎";
default:
return keystroke;
}
}
+6
View File
@@ -65,6 +65,7 @@ export default class CoreViewModel {
if (!(e instanceof KeyboardEvent))
return console.trace("NOT A KEY EVENT");
if (CoreViewModel.checkIsKeystroke(e) == false) return;
document.body.setAttribute("keystroke-active", "");
e.preventDefault();
const contexts: Context[] = this.contexts;
while (contexts.length > 0) {
@@ -75,6 +76,10 @@ export default class CoreViewModel {
}
};
handleKeyUp = (): void => {
document.body.removeAttribute("keystroke-active");
};
// CHRON
chronHandlerManager = new HandlerManager<void>();
todayDate = new React.State<Date>(new Date());
@@ -154,6 +159,7 @@ export default class CoreViewModel {
});
document.body.addEventListener("keydown", this.handleKeyDown);
document.body.addEventListener("keyup", this.handleKeyUp);
window.onpopstate = () => {
if (!this.context) return;
+1 -1
View File
@@ -324,7 +324,7 @@ export default class BoardViewModel extends TaskContainingPageViewModel {
// keystrokes
this.registerKeyStroke(CommonKeys.Filter, this.showFilterModal);
this.registerKeyStroke(CommonKeys.Reset, this.resetFilter);
this.registerKeyStroke(CommonKeys.Reset, this.resetFilter); //
this.registerKeyStroke(CommonKeys.CloseOrCancel, this.hideFilterModal);
this.registerKeyStroke(CommonKeys.Settings, this.showSettings);
this.registerKeyStroke(CommonKeys.Apply, this.hideSettings);
+34
View File
@@ -113,3 +113,37 @@ body[theme="dark"] #background-wrapper #grass-2 {
padding: var(--content-padding);
}
/* Keystrokes */
[ctkeystroke] {
position: relative;
}
[ctkeystroke]::after {
content: attr(ctkeystroke);
background: var(--primary);
color: var(--text-on-color);
--size: 24px;
position: absolute;
top: calc(50% - var(--size) / 2);
left: calc(50% - var(--size) / 2);
width: var(--size);
height: var(--size);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transform: translateY(10px);
transition: all calc(var(--animation-duration) / 2);
}
body[keystroke-active] [ctkeystroke]::after {
opacity: 1;
transform: translateY(0px);
}