Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
55a38cb
WIP move to ESM
hovancik May 1, 2025
541f407
Fixup WelcomeWIn
hovancik May 10, 2025
93d6da9
More changes
hovancik May 17, 2025
314700d
Contributor prefs
hovancik May 25, 2025
eb30045
Small fixes
hovancik May 25, 2025
7890ae6
Small fix with handlers
hovancik May 29, 2025
1703d5c
More fixes
hovancik May 29, 2025
c73ae7e
Update DBUS installation step to include package update
hovancik May 29, 2025
6b89217
More changes
hovancik Jun 7, 2025
50885af
More changes
hovancik Jun 8, 2025
330b8d6
Simplify
hovancik Jun 22, 2025
3ee19d6
Remove deprecated Quiet Hours checks and related dependencies
hovancik Jun 26, 2025
164af7d
Fixes
hovancik Jun 27, 2025
f61e763
Remove duplication
hovancik Jun 27, 2025
da780b8
Another updates
hovancik Jun 28, 2025
4616657
Improve notifications
hovancik Jul 1, 2025
b999caa
Add Plan mode for GH Copilot
hovancik Jul 3, 2025
ba60d0b
Refactor
hovancik Jul 3, 2025
8eab816
Refactor 2
hovancik Jul 4, 2025
fd2f82a
Update instructions for Copilot
hovancik Jul 4, 2025
11a20a5
Up some deps
hovancik Jul 8, 2025
10baf05
Fixup old syntax
hovancik Jul 8, 2025
e95cac2
Update electron, node
hovancik Jul 9, 2025
ef7a5c1
Refactor
hovancik Jul 10, 2025
fc7445a
Update app/utils/utils.js
hovancik Jul 13, 2025
86fc949
Revert dev changes
hovancik Jul 13, 2025
8ae0c46
Tamil language option
hovancik Jul 13, 2025
172914e
Rename
hovancik Jul 13, 2025
2dfaf9d
Never show bart
hovancik Jul 13, 2025
54a7ce1
Update
hovancik Jul 15, 2025
d4f9cef
Remove dev tools
hovancik Jul 16, 2025
ed22d89
Never wanna play sound here
hovancik Jul 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/chatmodes/Plan.chatmode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
description: Generate an implementation plan for new features or refactoring existing code.
tools: ['codebase', 'fetch', 'findTestFiles', 'githubRepo', 'search', 'usages']
---
# Planning mode instructions
You are in planning mode. Your task is to generate an implementation plan for a new feature or for refactoring existing code.

Create a plan that is simple and easy to follow. Do not make a lot of changes, but prefer small, incremental updates changing one thing at a time. If you see multiple ways of implementing a feature or refactoring code, lead a discussion to evaluate the options with the user.

Don't make any code edits, just generate a plan.

The plan consists of a Markdown document that describes the implementation plan, including the following sections:

* Overview: A brief description of the feature or refactoring task.
* Requirements: A list of requirements for the feature or refactoring task.
* Implementation Steps: A detailed list of steps to implement the feature or refactoring task.
* Testing: A list of tests that need to be implemented to verify the feature or refactoring task.
* Comments in code: Only if neccessary, when the code is not self-explanatory.

29 changes: 29 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Stretchly Development Assistant

You are a specialized assistant for developers working on Stretchly, a break-time reminder application that encourages regular stretching and healthy work habits.

## Technical Stack
- ElectronJS for cross-platform desktop functionality
- NodeJS backend
- JavaScript (following StandardJS style guidelines) using ESM (ECMAScript Modules)
- HTML and CSS for UI components

## Development Guidelines
- Follow StandardJS style (like no semicolons, 2-space indentation)
- Prefer ES6+ features (like arrow functions, destructuring, etc.)
- Maintain cross-platform compatibility (Windows, macOS, Linux)
- Use appropriate Electron APIs for native functionality
- Maintain accessibility standards in UI components
- Keep performance in mind, especially for background processes
- Consider Chrome compatibility only, as Electron is built on Chromium

## Code Organization
- Respect the existing project structure
- Place new functionality in appropriate modules
- Follow the established patterns for event handling

## Testing Expectations
- Suggest tests for new functionality
- Consider edge cases in different operating systems

When suggesting code changes, explain your reasoning and how they align with Stretchly's goals of promoting healthy computer use.
2 changes: 1 addition & 1 deletion .github/workflows/arm-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '20.18.1'
node-version: '22.17.0'
- run: sudo apt update && sudo apt-get install --no-install-recommends -y ruby-full libarchive-tools
- run: sudo gem install fpm -v 1.15
- run: npm install npm -g
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
python-version: '3.12'
- uses: actions/setup-node@v3
with:
node-version: '20.18.1'
node-version: '22.17.0'
- run: pip install setuptools
- run: npm install npm -g
- run: npm install
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/snap-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '20.18.1'
node-version: '22.17.0'
- run: pip install setuptools
- run: npm install -g npm
- run: npm install
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
if: matrix.os == 'ubuntu-latest'
run: |
export DISPLAY=:0
sudo apt install dbus-x11
sudo apt update && sudo apt install dbus-x11
machineId=$(cat /var/lib/dbus/machine-id)
mkdir -p /home/runner/.dbus
mkdir -p /home/runner/.dbus/session-bus/
Expand All @@ -46,7 +46,7 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: '20.18.1'
node-version: '22.17.0'
- run: pip install setuptools
- run: npm install npm -g
- run: npm install
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20.18.1
22.17.0
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Added
- Yiddish translations
- Yiddish and Tamil translations

### Changed
- remove flags in Welcome window
- updated many translations
- do not check for Quiet Hours on Windows (deprecated)

### Fixed
- hide close/minimize actions on Break window on macOS
Expand Down
15 changes: 15 additions & 0 deletions app/break-preload.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {
exposeBreaks,
exposeI18next,
exposeProcess,
exposeSettings,
exposeStretchly,
exposeUtils
} from './utils/context-bridge-exposers.js'

exposeBreaks('long')
exposeI18next()
exposeProcess()
exposeSettings()
exposeStretchly()
exposeUtils()
55 changes: 55 additions & 0 deletions app/break-renderer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import HtmlTranslate from './utils/htmlTranslate.js'
import './platform.js'

window.onload = async (event) => {
const [idea, started, duration, strictMode, postpone,
postponePercent, backgroundColor] = await window.breaks.sendBreakData()

new HtmlTranslate(document).translate()

document.ondragover = event =>
event.preventDefault()

document.ondrop = event =>
event.preventDefault()

document.querySelector('#close').onclick = async event =>
await window.breaks.finishBreak()

document.querySelector('#postpone').onclick = async event =>
await window.breaks.postponeBreak()

document.querySelector('.break-idea').textContent = idea[0]
document.querySelector('.break-text').textContent = idea[1]

const progress = document.querySelector('#progress')
const progressTime = document.querySelector('#progress-time')
const postponeElement = document.querySelector('#postpone')
const closeElement = document.querySelector('#close')
const mainColor = await window.settings.get('mainColor')
document.body.classList.add(mainColor.substring(1))
document.body.style.backgroundColor = backgroundColor

document.querySelectorAll('.tiptext').forEach(async tt => {
const keyboardShortcut = await window.settings.get('endBreakShortcut')
tt.innerHTML = await window.utils.formatKeyboardShortcut(keyboardShortcut)
})

setInterval(async () => {
if (await window.settings.get('currentTimeInBreaks')) {
document.querySelector('.breaks > :last-child').innerHTML =
(new Date()).toLocaleTimeString()
}
if (Date.now() - started < duration) {
const passedPercent = (Date.now() - started) / duration * 100
postponeElement.style.display =
await window.utils.canPostpone(postpone, passedPercent, postponePercent) ? 'flex' : 'none'
closeElement.style.display =
await window.utils.canSkip(strictMode, postpone, passedPercent, postponePercent) ? 'flex' : 'none'
progress.value = (100 - passedPercent) * progress.max / 100
progressTime.innerHTML = await window.utils.formatTimeRemaining(Math.trunc(duration - Date.now() + started),
await window.settings.get('language'))
}
}, 100)
await window.breaks.signalLoaded()
}
1 change: 1 addition & 0 deletions app/break.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@
</div>
</div>
</body>
<script type="module" src="./break-renderer.js"></script>
</html>
65 changes: 0 additions & 65 deletions app/break.js

This file was deleted.

14 changes: 7 additions & 7 deletions app/breaksPlanner.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const Scheduler = require('./utils/scheduler')
const EventEmitter = require('events')
const NaturalBreaksManager = require('./utils/naturalBreaksManager')
const DndManager = require('./utils/dndManager')
const AppExclusionsManager = require('./utils/appExclusionsManager')
const log = require('electron-log/main')
import Scheduler from './utils/scheduler.js'
import EventEmitter from 'events'
import NaturalBreaksManager from './utils/naturalBreaksManager.js'
import DndManager from './utils/dndManager.js'
import AppExclusionsManager from './utils/appExclusionsManager.js'
import log from 'electron-log/main.js'

class BreaksPlanner extends EventEmitter {
constructor (settings) {
Expand Down Expand Up @@ -289,4 +289,4 @@ class BreaksPlanner extends EventEmitter {
}
}

module.exports = BreaksPlanner
export default BreaksPlanner
9 changes: 9 additions & 0 deletions app/contributor-preferences-preload.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {
exposeI18next,
exposeProcess,
exposeSettings
} from './utils/context-bridge-exposers.js'

exposeI18next()
exposeProcess()
exposeSettings()
75 changes: 75 additions & 0 deletions app/contributor-preferences-renderer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import HtmlTranslate from './utils/htmlTranslate.js'
import { setSameWidths } from './utils/sameWidths.js'
import './platform.js'

let eventsAttached = false

window.onload = async (event) => {
const settings = await window.settings.currentSettings()
setTimeout(() => { eventsAttached = true }, 500)

document.ondragover = event =>
event.preventDefault()

document.ondrop = event =>
event.preventDefault()

document.querySelectorAll('input[type="checkbox"]').forEach(checkbox => {
const isNegative = checkbox.classList.contains('negative')
checkbox.checked = isNegative ? !settings[checkbox.value] : settings[checkbox.value]
if (!eventsAttached) {
checkbox.onchange = (event) =>
window.settings.saveSettings(checkbox.value,
isNegative ? !checkbox.checked : checkbox.checked)
}
})

document.querySelectorAll('input[type="radio"]').forEach(radio => {
let value
switch (radio.value) {
case 'true':
value = true
break
case 'false':
value = false
break
default:
value = radio.value
}
radio.checked = settings[radio.name] === value
if (!eventsAttached) {
radio.onchange = (event) => {
window.settings.saveSettings(radio.name, value)
}
}
})

document.querySelectorAll('select').forEach(select => {
select.value = settings[select.name]
if (!eventsAttached) {
select.onchange = (event) => {
window.settings.saveSettings(select.name, select.value)
}
}
})

document.querySelectorAll('input[type="range"]').forEach(async range => {
const divisor = range.dataset.divisor
const output = range.closest('div').querySelector('output')
range.value = settings[range.name] / divisor
const unit = output.dataset.unit
output.innerHTML = await window.i18next.t(`utils.${unit}`, { count: parseInt(range.value) })
if (!eventsAttached) {
range.onchange = async event => {
output.innerHTML = await window.i18next.t(`utils.${unit}`, { count: parseInt(range.value) })
window.settings.saveSettings(range.name, range.value * divisor)
}
range.oninput = async event => {
output.innerHTML = await window.i18next.t(`utils.${unit}`, { count: parseInt(range.value) })
}
}
})

new HtmlTranslate(document).translate()
setSameWidths()
}
1 change: 1 addition & 0 deletions app/contributor-preferences.html
Original file line number Diff line number Diff line change
Expand Up @@ -493,4 +493,5 @@
</div>
</div>
</body>
<script type="module" src="./contributor-preferences-renderer.js"></script>
</html>
Loading
Loading