Commit f5dd1258 authored by ransome1's avatar ransome1
Browse files

Merge branch 'develop' into ipc

parents 6eebcb67 7a16552b
......@@ -3,24 +3,22 @@
## What is needed?
### Refactor JavaScript
sleek is written in plain vanilla JavaScript. I'm doing my best to keep the code as slim and tidy as possible. But I'm not a professional developer and limited on time I can invest in this project. You can contribute by reviewing the JavaScript with the aim of making sleek faster and more maintainable.
sleek is written in plain vanilla JavaScript. I'm doing my best to keep the code as slim and tidy as possible. But I'm not a professional developer and limited on time I can invest into this project. You can contribute by reviewing the JavaScript with the aim of making sleek faster and more maintainable.
### Clean up the CSS
In order to create sleeks' unique look lot of (S)CSS had been written. If you have experience on CSS you can review and optimise it.
In order to create sleeks' unique look a lot of (S)CSS had been written. If you have experience in CSS you can review and optimise it.
### Work on feature requests
Over the time plenty of feature requests had been files for sleek: https://github.com/ransome1/sleek/issues. You can simply pick feature request and start working on it. Every feature needs to be contributed with a sufficient amount of test cases (see "Write test cases"). There is a prioritised backlog too: https://github.com/ransome1/sleek/projects/2
Over the time plenty of feature requests had been added to sleeks backlog: https://github.com/ransome1/sleek/issues. You can simply pick a feature request and start working on it. Every feature needs to be contributed with a sufficient amount of test cases (see "Write test cases"). There is a prioritised backlog too: https://github.com/ransome1/sleek/projects/2
### Enhance the CI process
sleek is being distributed through Github and many other platforms (Snap Store, Flathub, Arch User Repository, Windows Store, Mac App Store). Releasing sleek is still plenty of work and it would be of great help if the releasing process would be further automated. For instance the build process on Flathub or AUR could be triggered on tag creation on Github. The current CI configuration can be found here: https://github.com/ransome1/sleek/blob/develop/.github/workflows/github-ci.yml
### Enhance the design
If you have interface design experience you can propose design changes. As sleek has a strong focus on its design all changes should be discussed before any implementation is being done.
If you have interface design experience you can propose design changes. As sleek has a strong focus on its design, all changes should be discussed before any implementation is being done.
### Translate sleek into your language
Plenty of languages are already available, but if yours is missing, you can translate the app to it.
## Write test cases
## File pull request
\ No newline at end of file
### Write test cases
Test cases are written for the Playwright end to end testing environment: https://playwright.dev/docs/api/class-playwright. Creating cases it pretty much straight forward and you can take a look on how it has been done so far: https://github.com/ransome1/sleek/blob/master/test/playwright.spec.js
\ No newline at end of file
MIT License
Copyright (c) 2021 Robin Ahle
Copyright (c) 2022 Robin Ahle
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
......
......@@ -2,6 +2,7 @@
## sleek is an open-source (FOSS) todo manager based on the todo.txt syntax. It's available for Windows, MacOS and Linux
+ [Screenshots](#screenshots)
+ [Support sleek](#support-sleek)
+ [Get it from Mac App Store](#get-sleek-from-apple-mac-app-store)
+ [Get it from Microsoft Store](#get-sleek-from-microsoft-store)
+ [Get it from Snap Store](#get-sleek-from-snap-store)
+ [Get it from Flathub](#get-sleek-from-flathub)
......@@ -22,34 +23,34 @@ sleek is available for Windows, MacOS and Linux, and in several languages. For a
### Screenshots
![Alt text](assets/screenshots/mac/main.png?raw=true "Screenshot of sleek's todo list view")
![Alt text](assets/screenshots/mac/drawer.png?raw=true "Screenshot of sleek's auto complete function and multi line todo feature")
![Alt text](assets/screenshots/mac/search.png?raw=true "Screenshot of sleek's todo list sorted by projects with due date picker shown")
### sleeks state of development
A prioritized backlog of new features and known issues as well as an overview on what is being worked on at the moment can be found <a href="https://github.com/ransome1/sleek/projects/2">here</a>.
### Support sleek
* Star, fork and watch it on Github.
* Review it on <a href="https://sourceforge.net/projects/sleek/reviews" target="blank">SourceForge</a> or <a href="https://www.microsoft.com/store/apps/9NWM2WXF60KR" target="blank">Windows Store</a>
* Contribute <a href="https://github.com/ransome1/sleek/issues">bug reports, code improvements or features</a>
* Translate sleek into your own language and contribute your translations
* Review it on <a href="https://apps.apple.com/us/app/sleek-todo-manager/id1614704209" target="blank">Mac App Store</a>, <a href="https://sourceforge.net/projects/sleek/reviews" target="blank">SourceForge</a> or <a href="https://www.microsoft.com/store/apps/9NWM2WXF60KR" target="blank">Windows Store</a>
* <a href="https://github.com/ransome1/sleek/blob/master/CONTRIBUTING.md">Contribute to sleek</a>
### Get sleek from Microsoft Store
You can install sleek from Microsofts Windows Store
### Get sleek from Apple Mac App Store
<a href="https://apps.apple.com/us/app/sleek-todo-manager/id1614704209" target="blank"><img src='assets/store_badges/Download_on_the_Mac_App_Store.png' alt='Get sleek from Apple Mac App Store' width='180'/></a>
### Get sleek from Microsoft Store
<a href="//www.microsoft.com/store/apps/9NWM2WXF60KR?cid=storebadge&ocid=badge" target="blank"><img src='https://developer.microsoft.com/store/badges/images/English_get-it-from-MS.png' alt='English badge' width='180'/></a>
### Get sleek from Snap Store
You can install sleek from Canonicals Snap Store using: `sudo snap install sleek`
[![Get it from the Snap Store](https://snapcraft.io/static/images/badges/en/snap-store-black.svg)](https://snapcraft.io/sleek)
Install sleek from <a href="https://snapcraft.io/sleek" target="blank">Snap Store</a> using: `sudo snap install sleek`
### Get sleek from Flathub
<a href="https://flathub.org/apps/details/com.github.ransome1.sleek" target="blank"><img width='180' alt="Download on Flathub" src="https://flathub.org/assets/badges/flathub-badge-en.png"/></a>
Install sleek from <a href="https://flathub.org/apps/details/com.github.ransome1.sleek" target="blank">Flathub</a> using: `flatpak install flathub com.github.ransome1.sleek`
Run it using: `flatpak run com.github.ransome1.sleek`
<a href="https://flathub.org/apps/details/com.github.ransome1.sleek" target="blank"><img width='180' alt="Download on Flathub" src="https://flathub.org/assets/badges/flathub-badge-en.png"/></a>
### Get sleek from Homebrew
Install sleek from <a href="https://formulae.brew.sh/cask/sleek" target="blank">Homebrew</a>.
`brew install --cask sleek`
......@@ -115,12 +116,16 @@ A more detailed documentation can be found in <a href="https://github.com/ransom
### Used libraries
- Electron: https://github.com/electron/electron
- Electron builder: https://github.com/electron-userland/electron-builder
- Electron Notarize: https://github.com/electron/electron-notarize
- Electron Windows Badge: https://github.com/viktor-shmigol/electron-windows-badge
- electron-reloader: https://github.com/sindresorhus/electron-reloader
- Bulma CSS: https://github.com/jgthms/bulma
- Font Awesome: https://github.com/FortAwesome/Font-Awesome
- jsTodoTxt: https://github.com/jmhobbs/jsTodoTxt
- Marked: https://github.com/markedjs/marked
- vanillajs-datepicker: https://github.com/mymth/vanillajs-datepicker
- i18next: https://github.com/i18next/i18next
- i18next-fs-backend: https://github.com/i18next/i18next-fs-backend
- Matomo: https://github.com/matomo-org/matomo
- chokidar: https://github.com/paulmillr/chokidar
- Sugar: https://github.com/andrewplummer/Sugar
......@@ -128,5 +133,3 @@ A more detailed documentation can be found in <a href="https://github.com/ransom
- Playwright: https://github.com/microsoft/playwright
- Sass: https://github.com/sass/sass
- eslint: https://github.com/eslint/eslint
- electron-reloader: https://github.com/sindresorhus/electron-reloader
- cross-env: https://github.com/kentcdodds/cross-env
......@@ -10,4 +10,4 @@ The following versions of sleek are provided with security updates.
## Reporting a Vulnerability
If you find a vulnerability in sleek, please send as much detail as possible to ransome@uber.space
If you find a vulnerability in sleek, please send as much detail as possible to ransome@duck.com
{
"name": "sleek",
"productName": "sleek",
"version": "1.1.7",
"version": "1.1.8-rc.5",
"description": "todo.txt manager for Linux, Windows and MacOS, free and open-source (FOSS)",
"synopsis": "todo.txt manager for Linux, Windows and MacOS, free and open-source (FOSS)",
"category": "ProjectManagement",
......@@ -11,7 +11,7 @@
"productivity",
"tasks"
],
"author": "Robin Ahle <mail@robbfolio.de>",
"author": "Robin Ahle <ransome@duck.com>",
"copyright": "Copyright © 2022 ${author}",
"license": "MIT",
"repository": "https://github.com/ransome1/sleek/",
......@@ -34,6 +34,7 @@
"!yarn.lock",
"!yarn-error.log",
"!assets/screenshots${/*}",
"!assets/store_badges${/*}",
"!**/node_modules/*/{CHANGELOG.md,README.md,README,readme.md,readme,test,__tests__,tests,powered-test,example,examples,*.d.ts}",
"!**/node_modules/.bin",
"!**/*.{o,hprof,orig,pyc,pyo,rbc}",
......@@ -120,6 +121,7 @@
},
"scripts": {
"build:mas": "yarn build:css && yarn build:pegjs && electron-builder -m mas --universal --publish never && bash build/resignPkg.sh",
"build:macos": "yarn build:css && yarn build:pegjs && electron-builder -m zip --universal --publish never && bash build/resignPkg.sh",
"build:appx": "yarn build:css && yarn build:pegjs && electron-builder -w appx --publish never",
"build:css": "sass src/scss/style.scss:src/css/style.css",
"build:pegjs": "peggy --format es --output src/js/filterlang.mjs src/js/filterlang.pegjs",
......@@ -130,7 +132,7 @@
"test1": "yarn playwright test -g 'Check if multi line items are displayed correctly' --config=test/playwright.config.js"
},
"dependencies": {
"@fortawesome/fontawesome-free": "^5.15.3",
"@fortawesome/fontawesome-free": "^6.1.1",
"bulma": "^0.9.2",
"chokidar": "^3.5.1",
"electron-updater": "^4.6.5",
......
const { AppImageUpdater } = require("electron-updater");
const { AppImageUpdater, MacUpdater } = require("electron-updater");
const autoUpdater = new AppImageUpdater();
function addEvents(element) {
element
.on("update-available", () => {
console.log("Update available");
})
.on("update-not-available", () => {
console.log("No update");
})
.on("error", (error) => {
console.log("Error in updater: " + error);
})
.on("download-progress", (progressObj) => {
let log_message = "Download speed: " + progressObj.bytesPerSecond;
log_message = log_message + " - Downloaded " + progressObj.percent + "%";
log_message = log_message + " (" + progressObj.transferred + "/" + progressObj.total + ")";
console.log(log_message);
})
.on("update-downloaded", () => {
console.log("Update downloaded");
});
}
autoUpdater.allowPrerelease = false;
const autoUpdaterAppImage = new AppImageUpdater();
autoUpdaterAppImage.allowPrerelease = false;
addEvents(autoUpdaterAppImage);
autoUpdater
.on("update-available", () => {
console.log("Update available");
})
.on("update-not-available", () => {
console.log("No update");
})
.on("error", (error) => {
console.log("Error in updater: " + error);
})
.on("download-progress", (progressObj) => {
let log_message = "Download speed: " + progressObj.bytesPerSecond;
log_message = log_message + " - Downloaded " + progressObj.percent + "%";
log_message = log_message + " (" + progressObj.transferred + "/" + progressObj.total + ")";
console.log(log_message);
})
.on("update-downloaded", () => {
console.log("Update downloaded");
});
const autoUpdaterMac = new MacUpdater();
autoUpdaterMac.allowPrerelease = false;
addEvents(autoUpdaterMac);
module.exports = autoUpdater;
\ No newline at end of file
module.exports = { autoUpdaterAppImage, autoUpdaterMac };
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -5,8 +5,9 @@ import { createModalJail } from "./jail.mjs";
import { getConfirmation } from "./prompt.mjs";
import { handleError } from "./helper.mjs";
const html = document.getElementById("html");
const addAsTodo = document.getElementById("addAsTodo");
const autoUpdateBody = document.getElementById("autoUpdateBody");
const autoUpdateHeadline = document.getElementById("autoUpdateHeadline");
const compactViewBody = document.getElementById("compactViewBody");
const compactViewHeadline = document.getElementById("compactViewHeadline");
const fileTabsBody = document.getElementById("fileTabsBody");
......@@ -15,7 +16,7 @@ const helpTab1Title = document.getElementById("helpTab1Title");
const helpTab2Title = document.getElementById("helpTab2Title");
const helpTab3Title = document.getElementById("helpTab3Title");
const helpTab4Title = document.getElementById("helpTab4Title");
const helpTab5Title = document.getElementById("helpTab5Title");
const recurrences = document.getElementById("recurrences");
const helpTabContextsProjectsBody = document.getElementById("helpTabContextsProjectsBody");
const helpTabContextsProjectsTitle = document.getElementById("helpTabContextsProjectsTitle");
const helpTabDatesBody1 = document.getElementById("helpTabDatesBody1");
......@@ -57,6 +58,8 @@ const helpTabPrioritiesBody = document.getElementById("helpTabPrioritiesBody");
const helpTabPrioritiesTitle = document.getElementById("helpTabPrioritiesTitle");
const helpTabRecurrencesBody1 = document.getElementById("helpTabRecurrencesBody1");
const helpTabRecurrencesTitle1 = document.getElementById("helpTabRecurrencesTitle1");
const html = document.getElementById("html");
const language = document.getElementById("language");
const modalWindows = document.querySelectorAll(".modal");
const reviewSourceforge = document.getElementById("reviewSourceforge");
const reviewWindowsStore = document.getElementById("reviewWindowsStore");
......@@ -68,8 +71,8 @@ const settingsTabAboutExternalLibraries = document.getElementById("settingsTabAb
const settingsTabAboutHeadline = document.getElementById("settingsTabAboutHeadline");
const settingsTabAboutPrivacy = document.getElementById("settingsTabAboutPrivacy");
const settingsTabAboutPrivacyBody = document.getElementById("settingsTabAboutPrivacyBody");
const settingsTabSettingsDarkmode = document.getElementById("settingsTabSettingsDarkmode");
const settingsTabSettingsDarkmodeBody = document.getElementById("settingsTabSettingsDarkmodeBody");
const themeHeadline = document.getElementById("themeHeadline");
const themeBody = document.getElementById("themeBody");
const settingsTabSettingsHeadline = document.getElementById("settingsTabSettingsHeadline");
const settingsTabSettingsLanguage = document.getElementById("settingsTabSettingsLanguage");
const settingsTabSettingsLanguageBody = document.getElementById("settingsTabSettingsLanguageBody");
......@@ -79,7 +82,7 @@ const settingsTabSettingsNotifications = document.getElementById("settingsTabSet
const settingsTabSettingsNotificationsBody = document.getElementById("settingsTabSettingsNotificationsBody");
const settingsTabSettingsTray = document.getElementById("settingsTabSettingsTray");
const settingsTabSettingsTrayBody = document.getElementById("settingsTabSettingsTrayBody");
const shareFacebook = document.getElementById("shareFacebook");
const reviewAppMacStore = document.getElementById("reviewWindowsStore");
const shareLinkedin = document.getElementById("shareLinkedin");
const shareTwitter = document.getElementById("shareTwitter");
const submitIssuesOnGithub = document.getElementById("submitIssuesOnGithub");
......@@ -87,9 +90,10 @@ const zoom = document.getElementById("zoom");
const zoomBody = document.getElementById("zoomBody");
const zoomHeadline = document.getElementById("zoomHeadline");
const zoomUndo = document.getElementById("zoomUndo");
const language = document.getElementById("language");
addAsTodo.innerHTML = translations.addAsTodo;
autoUpdateBody.innerHTML = translations.autoUpdateBody;
autoUpdateHeadline.innerHTML = translations.autoUpdateHeadline;
compactViewBody.innerHTML = translations.compactViewBody;
compactViewHeadline.innerHTML = translations.compactView;
fileTabsBody.innerHTML = translations.fileTabsBody;
......@@ -98,7 +102,7 @@ helpTab1Title.innerHTML = translations.shortcuts;
helpTab2Title.innerHTML = translations.priorities;
helpTab3Title.innerHTML = translations.helpTab3Title;
helpTab4Title.innerHTML = translations.helpTab4Title;
helpTab5Title.innerHTML = translations.helpTab5Title;
recurrences.innerHTML = translations.recurrences;
helpTabContextsProjectsBody.innerHTML = translations.helpTabContextsProjectsBody;
helpTabContextsProjectsTitle.innerHTML = translations.helpTabContextsProjectsTitle;
helpTabDatesBody1.innerHTML = translations.helpTabDatesBody1;
......@@ -142,6 +146,7 @@ helpTabRecurrencesBody1.innerHTML = translations.helpTabRecurrencesBody1;
helpTabRecurrencesTitle1.innerHTML = translations.helpTabRecurrencesTitle1;
reviewSourceforge.innerHTML = translations.reviewSourceforge;
reviewWindowsStore.innerHTML = translations.reviewWindowsStore;
reviewMacAppStore.innerHTML = translations.reviewMacAppStore;
settingsTabAbout.innerHTML = translations.about;
settingsTabAboutContribute.innerHTML = translations.settingsTabAboutContribute;
settingsTabAboutCopyrightLicense.innerHTML = translations.settingsTabAboutCopyrightLicense;
......@@ -150,8 +155,8 @@ settingsTabAboutExternalLibraries.innerHTML = translations.settingsTabAboutExter
settingsTabAboutHeadline.innerHTML = translations.about;
settingsTabAboutPrivacy.innerHTML = translations.settingsTabAboutPrivacy;
settingsTabAboutPrivacyBody.innerHTML = translations.settingsTabAboutPrivacyBody;
settingsTabSettingsDarkmode.innerHTML = translations.darkmode;
settingsTabSettingsDarkmodeBody.innerHTML = translations.settingsTabSettingsDarkmodeBody;
themeHeadline.innerHTML = translations.themeHeadline;
themeBody.innerHTML = translations.themeBody;
settingsTabSettingsHeadline.innerHTML = translations.settings;
settingsTabSettingsLanguage.innerHTML = translations.language;
settingsTabSettingsLanguageBody.innerHTML = translations.settingsTabSettingsLanguageBody;
......@@ -161,7 +166,6 @@ settingsTabSettingsNotifications.innerHTML = translations.notifications;
settingsTabSettingsNotificationsBody.innerHTML = translations.settingsTabSettingsNotificationsBody;
settingsTabSettingsTray.innerHTML = translations.settingsTabSettingsTray;
settingsTabSettingsTrayBody.innerHTML = translations.settingsTabSettingsTrayBody;
shareFacebook.innerHTML = translations.shareFacebook;
shareLinkedin.innerHTML = translations.shareLinkedin;
shareTwitter.innerHTML = translations.shareTwitter;
submitIssuesOnGithub.innerHTML = translations.submitIssuesOnGithub;
......@@ -180,6 +184,15 @@ language.onchange = function() {
// trigger matomo event
if(userData.matomoEvents) _paq.push(["trackEvent", "Settings", "Language changed to: " + this.value]);
}
theme.onchange = function() {
// only continue if language code has been passed
if(!this.value) return false;
window.api.send("setTheme", this.value)
// trigger matomo event
if(userData.matomoEvents) _paq.push(["trackEvent", "Settings", "Theme changed to: " + this.value]);
}
zoom.onchange = function() {
setZoom(this.value).then(response => {
console.log(response);
......@@ -201,7 +214,6 @@ zoomUndo.onclick = function() {
function setZoom(value) {
try {
// manipulate dom
html.style.zoom = value + "%";
......@@ -264,6 +276,10 @@ function setFriendlyLanguageNames() {
export function showModal(modalId) {
try {
// TODO: make this more generic
// set the theme selection field
document.getElementById("theme").value = userData.theme;
// in case a content window was open, it will be closed
modalWindows.forEach(function(modalWindow) { modalWindow.classList.remove("is-active") });
......
......@@ -121,7 +121,7 @@ modalForm.onsubmit = async function(event) {
return false;
// check if todo text is empty
} else if(!todo.text && !todo.h) {
} else if(!todo.text) {
modalFormAlert.innerHTML = translations.formInfoIncomplete;
modalFormAlert.parentElement.classList.add("is-active", "is-warning");
console.log("Info: Todo is incomplete");
......@@ -490,13 +490,7 @@ async function show(todo, templated) {
}
// if there is a recurrence
if(todo.rec) {
setInput(todo.rec).then(function(result) {
console.log(result);
}).catch(function(error) {
handleError(error);
});
}
if(todo.rec) setInput(todo.rec)
// if so we paste it into the input field
if(todo.dueString) datePickerInput.value = todo.dueString;
}
......
......@@ -30,6 +30,7 @@ const renderer = {
};
marked.use({ renderer });
// TODO: check if this still works
export function jumpToItem(item) {
try {
const isInViewport = function(item) {
......@@ -173,9 +174,8 @@ export function initialSetupInterface() {
// setup compact view
(userData.compactView) ? body.classList.add("compact") : body.classList.remove("compact");
// setup darkmode
window.api.send("darkmode", userData.darkmode);
(userData.darkmode) ? body.classList.add("dark") : body.classList.remove("dark");
// show or hide specific settings
if(appData.channel === "AppImage" || appData.os === "mac" && appData.channel !== "Mac App Store") document.getElementById("autoUpdate").classList.remove("is-hidden")
// set scaling factor if default font size has changed
document.getElementById("html").style.zoom = userData.zoom + "%";
......
......@@ -6,9 +6,6 @@ import { showDrawer } from "./drawer.mjs";
import { resetFilters } from "./filters.mjs";
import { triggerToggle } from "./toggles.mjs";
//const helper = await import("./helper.mjs");
//const render = await import("../render.js");
// receives todo.txt data from main process as string and passes it to build function
window.api.receive("buildTable", (args) => {
buildTable(...args).then(function(response) {
......@@ -85,13 +82,6 @@ window.api.receive("triggerFunction", async (name, args) => {
handleError(error);
});
break;
case "toggleDarkmode":
triggerToggle(document.getElementById("darkmode"), true).then(function(response) {
console.info(response);
}).catch(function(error) {
handleError(error);
});
break;
case "toggle":
triggerToggle(document.getElementById(...args), true).then(function(response) {
console.info(response);
......
......@@ -4,7 +4,7 @@ import { getConfirmation } from "./prompt.mjs";
import { pasteItemsToClipboard, setDueDate } from "./helper.mjs";
import { removeFileFromList } from "./files.mjs";
import { resetFilters } from "./filters.mjs";
import { handleError } from "./helper.mjs";
import { handleError, getActiveFile } from "./helper.mjs";
import { show, setPriority, resetForm } from "./form.mjs";
import { showDrawer } from "./drawer.mjs";
import { showModal } from "./content.mjs";
......@@ -58,8 +58,10 @@ export async function registerShortcuts() {
if(event.key === "Escape") {
// if search is focused, lose focus on escape
// hide add todo button
if(document.activeElement.id==="todoTableSearch") {
todoTableSearch.blur();
document.getElementById("todoTableSearchAddTodo").classList.remove("is-active");
return false;
}
// if 'add as todo' is focused, return to search
......@@ -147,7 +149,7 @@ export async function registerShortcuts() {
if(isModalOpen()) {
// // set priority directly
// if(event.altKey && event.metaKey && event.key.length === 1 && event.key.match(/[A-Z]/i)) {
// if(event.altKey && event.key.length === 1 && event.key.match(/[A-Z]/i)) {
// setPriority(event.key.substr(0,1)).then(response => {
// console.log(response);
......@@ -472,7 +474,7 @@ export async function registerShortcuts() {
// priority up
if(event.ctrlKey && event.metaKey && event.key === "ArrowUp") {
if(event.altKey && event.metaKey && event.key === "ArrowUp") {
setPriority(-1).then(function(result) {
console.log(result);
}).catch(function(error) {
......@@ -483,7 +485,7 @@ export async function registerShortcuts() {
// priority down
if(event.ctrlKey && event.metaKey && event.key === "ArrowDown") {
if(event.altKey && event.metaKey && event.key === "ArrowDown") {
setPriority(1).then(function(result) {
console.log(result);
}).catch(function(error) {
......@@ -494,9 +496,11 @@ export async function registerShortcuts() {
// set priority directly
if(event.ctrlKey && event.metaKey && event.key.length === 1 && event.key.match(/[A-Z]/i)) {
if(event.altKey && event.metaKey && event.key.length === 1) {
setPriority(event.key.toUpperCase()).then(response => {
if(!event.code.includes("Key")) return false
setPriority(event.code.substr(3).toUpperCase()).then(response => {
console.log(response);
}).catch(error => {
handleError(error);
......@@ -508,7 +512,7 @@ export async function registerShortcuts() {
// remove priority
if(event.ctrlKey && event.metaKey && (event.key === "ArrowRight" || event.key === "ArrowLeft")) {
if(event.altKey && event.metaKey && (event.key === "ArrowRight" || event.key === "ArrowLeft")) {
setPriority(false).then(response => {
console.log(response);
......@@ -556,14 +560,10 @@ export async function registerShortcuts() {
return false;
}
// toggle dark mode
// toggle appearance
if(event.key==="d" && !isInputFocused()) {
triggerToggle(document.getElementById("darkmode"), true).then(function(response) {
console.info(response);
}).catch(function(error) {
handleError(error);
});
window.api.send("setTheme")
return false;
}
......
......@@ -4,9 +4,10 @@ import { handleError } from "./helper.mjs";
import { _paq } from "./matomo.mjs";
import { resizeInput } from "./form.mjs";
import { RecExtension } from "./todotxtExtensions.mjs";
import { generateTodoTxtObject, items, editTodo } from "./todos.mjs";
import * as recurrences from "./recurrences.mjs";
const radioRecurrence = document.querySelectorAll("#recurrencePicker .selection");
const radioRecurrence = document.querySelectorAll("#recurrencePickerContainer .selection");
const recurrencePickerContainer = document.getElementById("recurrencePickerContainer");
const recurrencePickerInput = document.getElementById("recurrencePickerInput");
const recurrencePickerSpinner = document.getElementById("recurrencePickerSpinner");
......@@ -30,9 +31,8 @@ recurrencePickerInput.placeholder = translations.noRecurrence;
recurrencePickerInput.onfocus = function(element) {
// only like this compatible with body click event in event.mjs
setTimeout(function() {
showRecurrences(element);
//this.blur();
}, 100);
showRecurrences(element.target, document.getElementById("modalFormInput").value);
}, 200);
};
recurrencePickerInput.onchange = function() {
......@@ -90,26 +90,24 @@ export function setInput(recurrence) {
} else {
recurrencePickerInput.value = null;
}
resizeInput(recurrencePickerInput);
// trigger matomo event
if(userData.matomoEvents) _paq.push(["trackEvent", "Form", "Recurrence selected: " + label]);
return Promise.resolve("Success: Recurrence added");
return label;
} catch(error) {
error.functionName = setInput.name;
return Promise.reject(error);
}
}
export function showRecurrences() {
export async function showRecurrences(trigger, todo) {
recurrencePickerContainer.focus();
// get position of current todo in array
const index = items.objects.map(function(item) { return item; }).indexOf(todo);
recurrencePickerContainer.classList.toggle("is-active");
document.getElementById("recurrencePickerIncrease").focus();
// get object from current input
let todo = new TodoTxtItem(document.getElementById("modalFormInput").value, [ new RecExtension() ]);
let recSplit = recurrences.splitRecurrence(todo.rec);
setRecurrenceOptionLabels(recSplit.mul);
recurrencePickerSpinner.value = recSplit.mul;
// function to apply recurrence's value on changes
const applyRecurrenceValue = function() {
let value = recSplit.toString();
......@@ -121,13 +119,39 @@ export function showRecurrences() {
todo.rec = undefined;
todo.recString = undefined;
}
setInput(value).then(function(result) {
console.log(result);
}).catch(function(error) {
handleError(error);
setInput(value);
if(trigger.id === "recurrencePickerInput") {
document.getElementById("modalFormInput").value = todo.toString();
document.getElementById("modalFormInput").focus();
return false;
}
if(index === -1) return false;
// finally pass new todo on for changing
editTodo(index, todo).then(response => {
console.log(response)
}).catch(error => {
console.log(error);
});
document.getElementById("modalFormInput").value = todo.toString();
}
const elementBounds = trigger.getBoundingClientRect();
recurrencePickerContainer.style.left = elementBounds.x + "px";
recurrencePickerContainer.style.top = elementBounds.y + elementBounds.height + "px";
recurrencePickerContainer.focus();
recurrencePickerContainer.classList.toggle("is-active");
document.getElementById("recurrencePickerIncrease").focus();
// create object if input is string