How can I get More Temporally Stable Face Landmarks!?  (ie less jitter)

I'm working on Windows 64bit and Python.
Iv'e made a basic opecv + mediapipe face track example. I started with this code,
https://pysource.com/2021/05/14/facial-landmarks-detection-with-opencv-mediapipe-and-python/
Mediapipe for Python <IP_ADDRESS>

Solution (e.g. FaceMesh, Pose, Holistic):  FaceMesh

Describe the expected behavior:
I would like the result to be stable over time. So it's not jittering and skipping around when looking at the resulting sequence.
I am not concerned about latency or execution duration.
Currently the fitting around eyes and mouth looks good but the overall fitting of the 'face plate' is skipping around quite a lot.
I would like it to looks smoothly stable as I watch it.
Standalone code you may have used to try to get what you need :
Currently setting up the FaceMesh like this,
face_mesh = mp_face_mesh.FaceMesh(static_image_mode=False, max_num_faces=1, refine_landmarks=True, min_detection_confidence=0.5, min_tracking_confidence=0.95)
I tried different min_tracking_confidence values.
How can achieve a more stable and less jittery result?
Cheers!

Hi and thank you very much for your reply and suggestions!
I will try that tool out and see if it is the solution I'm looking for!
Cheers

Hi @Fredrum ,
Can you close this issue if you have solution now.

@matthewwiese ,
Please open new issue for javascript based solutions.


ngraph ops implementation

Can now switch between vanilla shogun and ngraph backends

@vigsterkr tests pass on both backends!

great work! 💃


Add Bolt protocol support

Add Bolt protocol support

As part of the Global GraphHack hackathon, we've been working on load testing Neo4j queries with JMeter.
Though it is possible to do so ATM with scripting, it is a bit cumbersome.
The goal of this PR is to add native support of the bolt protocol in JMeter, through

a bolt connection configuration
a bolt request sampler

that are much alike other existing database elements.
Motivation and Context
The goal is to help people willing to do performance testing on Neo4j.
Please check, the link to the hackathon submission above.
We would be pleased to see the bolt support added to the JMeter codebase.
How Has This Been Tested?

We did created sample test plans for testing. They are available here
Gradle check and test run fine.
However, the PR may require some changes because the builds complains about signature checks, and I'm not sure how to solve this.
Screenshots (if appropriate):
There is a video demonstrating usage here https://youtu.be/Zqyeo0iShF4
Screenshots are also included  in the PR as part of the documentation change.
Types of changes

New feature (non-breaking change which adds functionality)

Checklist:

[X] My code follows the code style of this project.
[X] I have updated the documentation accordingly.

Hello @nmervaillie ,
Can you add to checksum.xml this as for now I don't see how to get pgp key for library (@vlsi , do you have an idea ?, by the way maybe it should be documented in contributing.md):
<dependency group='org.neo4j.driver' module='neo4j-java-driver' version='1.7.5'>
  <sha512>1767AC9E46C358E731FD91F895EF50B36216EB162E12A74957A6E3727A54A5C7C7E89303702F535876297A0ED067A689488CB5ACC977CA9E647665FAAE6C2E38</sha512>
</dependency>

Can you add to checksum.xml this as for now I don't see how to get pgp key for library

I don't quite follow you.
When I add "org.neo4j.driver:neo4j-java-driver:1.7.5" dependency I get the following error:
Execution failed for task ':src:core:dependencies'.
> Checksum/PGP violations detected on resolving configuration :src:core:compileClasspath
    No trusted PGP keys are configured for group org.neo4j.driver:
      org.neo4j.driver:neo4j-java-driver:1.7.5 (pgp=[7ad289796be2ffe2], sha512=[computation skipped])

It displays the PGP key id. Of course we don't know if that is the official one, however, that is yet another story.
I think we should refrain from adding "sha512-only" entries to checksum.xml because it is not that easy to verify if the given sha is authentic or not.

A side note: Neo4j java driver recommends to use a connection pool

Can you add to checksum.xml this as for now I don't see how to get pgp key for library

I don't quite follow you.
When I add "org.neo4j.driver:neo4j-java-driver:1.7.5" dependency I get the following error:
Execution failed for task ':src:core:dependencies'.
> Checksum/PGP violations detected on resolving configuration :src:core:compileClasspath
    No trusted PGP keys are configured for group org.neo4j.driver:
      org.neo4j.driver:neo4j-java-driver:1.7.5 (pgp=[7ad289796be2ffe2], sha512=[computation skipped])

It displays the PGP key id. Of course we don't know if that is the official one, however, that is yet another story.

So isn't it more dangerous to add this php as trusted signer ?
Than using the sha512 ? by getting it from maven central

I think we should refrain from adding "sha512-only" entries to checksum.xml because it is not that easy to verify if the given sha is authentic or not.

So isn't it more dangerous to add this php as trusted signer ?

I would refrain from PHP :)

Than using the sha512 ? by getting it from maven central

Central does not provide SHA512.
Central is not an authoritative source for "the official SHA512"
Please consider what steps Apache JMeter recommends to use in order to verify a download: https://jmeter.apache.org/download_jmeter.cgi
There's no item like "download JMeter from Central and compute checksum".
The very same thing should be used for other dependencies.

testing a Neo4j configuration and queries should we pool ?

I gues we sould pool in order to support cases like "1000-10000 clients" with reasonable think times.
Do you really expect JMeter should keep 10_000 connections in that case?

Can you add to checksum.xml this as for now I don't see how to get pgp key for library

I don't quite follow you.
When I add "org.neo4j.driver:neo4j-java-driver:1.7.5" dependency I get the following error:
Execution failed for task ':src:core:dependencies'.
> Checksum/PGP violations detected on resolving configuration :src:core:compileClasspath
    No trusted PGP keys are configured for group org.neo4j.driver:
      org.neo4j.driver:neo4j-java-driver:1.7.5 (pgp=[7ad289796be2ffe2], sha512=[computation skipped])

It displays the PGP key id. Of course we don't know if that is the official one, however, that is yet another story.
I think we should refrain from adding "sha512-only" entries to checksum.xml because it is not that easy to verify if the given sha is authentic or not.

@vlsi Sorry I don't get what we should do about how the signing process works. Any guidance or pointers would help. Should we ask the Neo4j driver team to add some signing process?

Should we ask the Neo4j driver team to add some signing process?

@nmervaillie , Please ask them to publish "the official signing key for Neo4j driver artifacts on the project website".
Here are some samples for inspiration:
https://gitlab.ow2.org/asm/asm/issues/317884
https://github.com/raphw/byte-buddy/issues/721
https://github.com/spring-projects/spring-framework/issues/23434#issuecomment-523882229
https://github.com/junit-team/junit5/issues/2020
https://github.com/hamcrest/JavaHamcrest/issues/274
https://github.com/jacoco/jacoco/issues/937
https://github.com/GPars/GPars/issues/62
https://youtrack.jetbrains.com/issue/KT-33781
Here's the motivation behind PGP verification: https://medium.com/@vladimirsitniko/dependency-verification-checksum-vs-pgp-582e76207019

A side note: Neo4j java driver recommends to use a connection pool

Actually the driver internally pools the connections

A side note: Neo4j java driver recommends to use a connection pool

Actually the driver internally pools the connections

@nmervaillie, so if we want to simulate without pool, we need to have 1 Driver instance per thread right ?
Do you think this scenario is useful ?

A side note: Neo4j java driver recommends to use a connection pool

Actually the driver internally pools the connections

@nmervaillie, so if we want to simulate without pool, we need to have 1 Driver instance per thread right ?
Do you think this scenario is useful ?

Correct.
I've never came across / heard about someone testing the pool initialization, so I'd say to leave this out for now. I don't really imagine a use case for it, or at least not as part of a load test.

A side note: Neo4j java driver recommends to use a connection pool

Actually the driver internally pools the connections

@nmervaillie, so if we want to simulate without pool, we need to have 1 Driver instance per thread right ?
Do you think this scenario is useful ?

Correct.
I've never came across / heard about someone testing the pool initialization, so I'd say to leave this out for now. I don't really imagine a use case for it, or at least not as part of a load test.
I'll add a note in the documentation about connection pooling

If you have N JVMs hitting a Neo4j instance, aren't they in the configuration where each instance has a Driver ?

A side note: Neo4j java driver recommends to use a connection pool

Actually the driver internally pools the connections

@nmervaillie, so if we want to simulate without pool, we need to have 1 Driver instance per thread right ?
Do you think this scenario is useful ?

Correct.
I've never came across / heard about someone testing the pool initialization, so I'd say to leave this out for now. I don't really imagine a use case for it, or at least not as part of a load test.
I'll add a note in the documentation about connection pooling

If you have N JVMs hitting a Neo4j instance, aren't they in the configuration where each instance has a Driver ?

True, but to me the goal is to test the server side, not the client side.

Just in case, this adds 2.6MiB neo4j-java-driver-1.7.5.jar which is the 4th biggest jar in JMeter distribution.

Just in case, this adds 2.6MiB neo4j-java-driver-1.7.5.jar which is the 4th biggest jar in JMeter distribution.

Is it a concern?

It is ok for now, however, it would be great if it could be optional.
I don't think Bolt protocol would be used often, so in most of the cases, it would increase download time and consume disk space.


Cuda Error in prune_ldm.py

Hi, I'm running the prune_ldm.py, and I got the following error in Line pruner.step().  Could you please let me know how to fix it?

Traceback (most recent call last):
File "prune_ldm.py", line 134, in
pruner.step()
File "/opt/conda/lib/python3.8/site-packages/torch_pruning/pruner/algorithms/metapruner.py", line 227, in step
for group in pruning_method():
File "/opt/conda/lib/python3.8/site-packages/torch_pruning/pruner/algorithms/metapruner.py", line 343, in prune_local
imp = self.estimate_importance(group, ch_groups=ch_groups)
File "/opt/conda/lib/python3.8/site-packages/torch_pruning/pruner/algorithms/metapruner.py", line 231, in estimate_importance
return self.importance(group, ch_groups=ch_groups)
File "/opt/conda/lib/python3.8/site-packages/torch/autograd/grad_mode.py", line 27, in decorate_context
return func(*args, **kwargs)
File "/opt/conda/lib/python3.8/site-packages/torch_pruning/pruner/importance.py", line 183, in call
local_imp = w.abs().pow(self.p).sum(1)
RuntimeError: CUDA error: device-side assert triggered
CUDA kernel errors might be asynchronously reported at some other API call,so the stacktrace below might be incorrect.
For debugging consider passing CUDA_LAUNCH_BLOCKING=1.

Same problem. How did you solve this problem?

hi, did you solve this error?


Sourcemap support for test files

I was wondering if this was on the roadmap, as it doesn't seem like there's an option to tell mocha-typescript to use sourcemaps when printing stacktraces on test failures.
I workaround this right now by using node-source-map-support on top of my test files, but it would be great if it could be integrated into this project. Perhaps a flag like --sourcemap to enable sourcemaps?

I've been using node-source-map-support too. I think this is more of a node issue and is not closely interdependent, but at the same time it is important feature when you develop TypeScript. I do not think I will add this as dependency in mocha-typescript directly but probably it should be added to the scaffolding section and eventually to future project generator templates.

Added to REDAME.md


add dssm model

for issue #138
Adapt dssm to new base_model.

Codecov Report

Merging #186 into 2.0 will decrease coverage by 3.24%.
The diff coverage is 71.79%.

@@           Coverage Diff            @@
##            2.0     #186      +/-   ##
========================================
- Coverage   100%   96.75%   -3.25%
========================================
  Files        15       16       +1
  Lines       300      339      +39
========================================
+ Hits        300      328      +28
- Misses        0       11      +11

Impacted Files
Coverage Δ

matchzoo/models/__init__.py
100% <100%> (ø)
:arrow_up:

matchzoo/models/dssm_model.py
71.05% <71.05%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 22601af...f29f8d1. Read the comment docs.


Add a new alternating_values SourceTool

Another way of implementing this would be:
def alternating_values(initial_value=False):
    return cycle([initial_value == True, initial_value == False])

but I think the version in this PR is a bit more readable ;-)

Current coverage is 78.26% (diff: 100%)

Merging #460 into master will increase coverage by 0.02%

@@             master       #460   diff @@
==========================================
  Files            31         31
  Lines          7204       7213     +9
  Methods           0          0
  Messages          0          0
  Branches          0          0
==========================================
+ Hits           5636       5645     +9
  Misses         1568       1568
  Partials          0          0

Powered by Codecov. Last update 0c9e4a9...9fbed05

That's cool. I don't know which I consider neater. Both nice :)

I also suggested to Dave adding a booleanised random_values function i.e. randomly on or off for a non-pwm device. But that's easy enough to achieve by processing random_values.

That's exactly what http://gpiozero.readthedocs.io/en/latest/api_tools.html#gpiozero.tools.booleanized is for ;-)

That's what I meant!

...which means a very inefficient third way of implementing this PR would be:
def alternating_values(initial_value=False):
    it = booleanized(cos_values(2), 0, 1)
    if not initial_value:
        it = negated(it)
    return it

;-)

Oh, that's nice. As I think I mentioned at PyConUK - source/values is by far my favourite bit of the library!

I'm thinking of adding ramping_values next, which will be like a 'linear' version of cos_values (i.e. a triangle wave).

Ahh - I was wondering when someone (or myself) would get around to a triangle wave! I wonder if there should be aliases like square_values and triangle_values for these things?

I wonder if there should be aliases like square_values and triangle_values for these things?

I'm not sure... I guess triangle_values could be aliased to ramping_values, but I think if we wanted a square_values function then it'd need a period parameter (which ramping_values will have).
Do you think I should make ramping_values output 0 -> 1 (like alternating_values effectively does), or -1 -> +1 (like cos_values does) ?  My inclination is the former. (Obviously either variant can be scaled to the other one afterwards)

Ah, good point about the period parameter. And yes, my gut says 0->1 as well. Scaling's easy enough to apply.


Need to escape spaces twice in script paths

This won't work. Running it in Bitbar runs the path as-is, so the full path is not passed as the first argument.
Run script|bash="/usr/local/bin/node" param1="/space here/a.js"
This works though:
Run script|bash="/usr/local/bin/node" param1="/space\\ here/a.js"
So we have to double-escape spaces in paths. Please make it so this isn't necessary, thanks!

This sounds like a side-effect of not quoting params in your script? Please confirm.

See #489


WIP/RFC: Cache model state renders in migrations

(This PR is the result of some fruitful work during the DjangoCongress JP 2019 sprint day)
Model state rendering happens a lot in larger migrations, but for the most part the resulting models are the same. this tries to reduce the amount of work that needs to happen for larger migration work (notably happens during testing)
For the stats on this: on my 2017 Macbook Pro, on what I would call a "decently large" project (241 models over 89 apps, 492 migrations), the total run time of migrating went from 230 seconds to 42 seconds (averaged over a lot of runs). The cache hit rate on this is roughly 90% (for a full run I found:
CACHE HITS  63867
CACHE MISSES  5985

)
So this makes the migration step during a test in CI much faster for us. But it obviously won't be a huge deal for migrating in production, since one rarely runs that many migrations in production.
I'm torn between performance and potentially missing an issue about correctness here, but I think this change would make sense at least behind some "useful for testing" flag.
(I am going to post something in the developers mailing list in a bit with some more context/other improvements I think are possible in this space in a bit)

As far as I can see right now, a similar caching happened as a first approach to the Django 1.8 release but cause significant problems, specifically with regards to relational fields. Relational fields (ForeignKey, OneToOneField, ManyToManyField) keep an instance reference to the related model in .related_model or the related fields in .related_fields. The problem now is, if you reuse a field (and you do because you're only calling list() on self.fields to copy but not deepcopy the list), you're screwing up references between the models that will cause trouble with RunSQL and other operations that use related field or model attributes.
https://github.com/django/django/blob/1d0bab0bfd77edcf1228d45bf654457a8ff1890d/django/db/models/fields/__init__.py#L495-L499
From my work on migrations, I see essentially 2 approaches that are viable and would lead to significant performance improvements:
1. Make the schema editor work with model states
There's a very old branch on my fork that tries to implement this approach: https://github.com/MarkusH/django/commits/schemaeditor-modelstate
I lost interest and eventually also didn't have the time to pursue this approach further. I think that's the better of the two approaches, as it gets rid of the piece of code that actually causes the slow behavior: turning a model state into a model class to be used in the schema editor.
However, making the schema editor backward compatible has been proven difficult and to be a huge pain (just check out the commits :wink: )
2. Don't resolve models/fields to instances but rely on string references.
This approach is IMO merely a workaround as it would allow us to cache the fields and models as you're doing in your PR. model._meta.get_field("author").related_model would not return <class 'myapp.models.Author'> but "myapp.Author". However, as far as I can tell, that's highly backward incompatible. And at this point, I also don't see a way to make this backward compatible.

Closing due to inactivity.


⚠ Bofrost.fr has degraded performance

In 6cb6a65, Bofrost.fr (https://www.bofrost.fr) experienced degraded performance:

HTTP code: 200
Response time: 926 ms

Resolved: Bofrost.fr performance has improved in 3117081.


Fixes issue #15466: adjust properties on adopoters form, allow for sc…

FIXES ISSUE #15466
…roll, set feature to fixed height, add media queries for various breakpoints to keep integrity of the feature for smartphones and small devices
Signed-off-by: Michael Paglione<EMAIL_ADDRESS>Hey, I just made a Pull Request!

Fixes behavior allowing users to now scroll through form:

*Button was not visible on small viewports, and clicking the feature filled the viewport, forcing users to refresh the page to get out. *
Fix: shows button on smaller viewports and makes the form collapsable:

:heavy_check_mark: Checklist

[ ] A changeset describing the change and affected packages. (more info)
[ ] Added or updated documentation
[ ] Tests for new functionality and regression tests for bug fixes
[x] Screenshots attached (for UI changes)
[x] All your commits have a Signed-off-by line in the message. (more info)

@pagman77 Thanks for the PR! Changes look fine to me, but prettier complains about the formatting, if you run prettier on the file I can approve and merge 👍

All good - no worries - thanks!


issue w/ unpublished branch and update

While sitting on an unpublished branch, with .modulo pointing to a different branch.  Doing an update somehow drops one into a VI merge.  Broken, fix soon.

fixed by removing branch support.


Health Check should test for Opps with at least 1 Contact Role but none marked Primary

Since various operations can leave Opportunities with at least one Contact Role, but none with isPrimary=TRUE, add a healthcheck test for this state.
Here's a POU post in which a user could have benefitted from this test:
https://powerofus.force.com/0D58000002LzPwC

**lurch: add

Tracking W-008562

This should only look for missing contact roles on Opportunities from Household Accounts. For non-Household Account Opportunities, it's fine for there to be no contacts connected.

To be complete, I'd suggest (only on Opps from HH Accounts as Judi says),
testing for two different things:

No Contact Role records at all (while I believe this can be achieved by
turning off the right trigger, I'd say it is very uncommon and worth
warning about).

1 or more existing Contact Role records but none with Primary=TRUE.

On Thu, Oct 29, 2015 at 1:47 PM, Judi Sohn<EMAIL_ADDRESS>wrote:

This should only look for missing contact roles on Opportunities from
Household Accounts. For non-Household Account Opportunities, it's fine for
there to be no contacts connected.
—
Reply to this email directly or view it on GitHub
https://github.com/SalesforceFoundation/Cumulus/issues/1785#issuecomment-152316419
.

Salesforce has determined that this issue will not be explored further.


Missing NLD 'Double Gangs On-Off Remote Switch' in the HA Netatmo integration

NLD - Double Gangs On-Off Remote Switch
I find my NLD - Double Gangs On-Off Remote Switch module in the JSON file loaded by pyatmo. However, it does not appear in the list of devices for the Netatmo integration in Home Assistant.
  {
    "id": "00:04:74:00:00:8a:b2:75",
    "type": "NLD",
    "name": "**REDACTED**",
    "setup_date":<PHONE_NUMBER>,
    "room_id": "521888878",
    "bridge": "00:04:74:22:29:ca"
  },
  {
    "id": "00:04:74:00:00:8a:b2:75#1",
    "type": "NLD",
    "setup_date":<PHONE_NUMBER>,
    "bridge": "00:04:74:22:29:ca"
  },
  {
    "id": "00:04:74:00:00:8a:b2:75#2",
    "type": "NLD",
    "setup_date":<PHONE_NUMBER>,
    "bridge": "00:04:74:22:29:ca"
  }

What must be done to see it appear?
Screenshot

Regards

Here is the return of the Netatm API homestatus method call:
 {
                    "battery_level": 3300,
                    "firmware_revision": 3,
                    "id": "00:04:74:00:00:8a:b2:75",
                    "last_seen":<PHONE_NUMBER>,
                    "otau_last_retry": 0,
                    "otau_last_seen":<PHONE_NUMBER>,
                    "otau_retries": 0,
                    "reachable": false,
                    "type": "NLD",
                    "uptime": 5859986,
                    "variant": "NLD:remote_control_double_on_off_dimmer",
                    "bridge": "00:04:74:22:29:ca",
                    "battery_state": "full"
 }

To my understanding this is a remote control that can't be controlled via the API. So instead of trying to control the remote control you should rather focus on the target of that.

@cgtobi Yes, this is a remote control
I would like to use events from this remote as triggers in Home Assistant
https://developer.legrand.com/Documentation/compatible-products/

That will not work unless they provide webhook events.


Support reply array

When I try to reply Array I get Error: Cannot serialize unknown data type
Seems like getContentType in reply https://github.com/arobson/rabbot/blob/master/src/amqp/queue.js#L72 returns application/octet-stream for array (meanwhile https://github.com/arobson/rabbot/blob/master/src/amqp/exchange.js#L52 array handles correctly)
Should I open PR or it will be fixed in v2?

May be it should return application/json for numbers and null by default?
With current behaviour there is no way to send number or null in body, I need check body manually for it and setup contentType in options.

@swarthy - if you want to publish an octet-stream without having to specify that that's what you're doing, using contentType, you can publish a Buffer.
See: https://github.com/arobson/rabbot/blob/master/docs/publishing.md#rabbotpublish-exchangename-options-connectionname-


Extend user documentation with inter-workload dependencies

Issues: #48, #211

Definition of Done
The PR shall be merged only if all items mentioned in CONTRIBUTING.md have been followed. In case an item is not applicable as described, please provide a short explanation in the description.

[x] All steps in CONTRIBUTING.md have been handled

I have changed the writing style to a more technical writing style.

Minor changes required.

Changes have been adopted.


v2.0.0

Add skip & limit methods

Changes Unknown when pulling 359ca626df03825bab52d982a2cf069d717eca13 on dev into ** on master**.


[Bug]: npm install not working without distutils

Version

[X] I'm using version 1.16

Known issues

[X] I've checked Known issues

Existing issues

[X] I've checked Existing issues

Advanced Preferences

[X] I've checked Advanced Preferences

What operating system are you using?
macOS
Operating System Version
macOS 15.1.1
Reproduction steps

I installed suggested node version 20.18.0
Checked out the source code
Run npm install inside the root directory

Reproduces how often: [What percentage of the time does it reproduce?]
Expected Behavior
npm install should run just fine.
Actual Behavior
npm installfails and I cannot setup the repository for development.
Relevant log output
File "/Users/devtobi/Development/repositories/github/stretchly/node_modules/node-gyp/gyp/gyp_main.py", line 42, in <module>
npm error     import gyp  # noqa: E402
npm error     ^^^^^^^^^^
npm error   File "/Users/devtobi/Development/repositories/github/stretchly/node_modules/node-gyp/gyp/pylib/gyp/__init__.py", line 9, in <module>
npm error     import gyp.input
npm error   File "/Users/devtobi/Development/repositories/github/stretchly/node_modules/node-gyp/gyp/pylib/gyp/input.py", line 19, in <module>
npm error     from distutils.version import StrictVersion
npm error ModuleNotFoundError: No module named 'distutils'

Code of Conduct

[X] I agree to follow this project's Code of Conduct

I actually already found the root cause for this problem. It looks like some dependency stretchly uses depends on node-gyp and calls some python code when executing.
This means it looks like Python needs to be installed on the local machine.
When using a up to date Python version like 3.12 or 3.13, distutils is no longer included out of the box and has to be installed manually. On mac this was as easy as running brew install python-setuptools but I don't know if its more complex for other operating systems.
The documentation in the README should include this information:

Python 3.x is required on the local machine
If a Python version higher than 3.12 is used python setuptools have to be additionally installed.

After installing those tools I can run npm install just fine.

As stated above npm install works fine now but I still get issues when trying to run the provided tests scripts.
I suppose start, dev, test and lintq are all relevant npm scripts when developing and trying to contribute to this project.
However only test is currently running on my machine.
Here are the logs for the other tasks:
start (in this case the app starts of for a short time and I see the language selection welcome screen, but the app instantly crashes):
2024-11-21 23:01:41.863 Electron[69539:715519] +[IMKClient subclass]: chose IMKClient_Modern
2024-11-21 23:01:41.863 Electron[69539:715519] +[IMKInputSession subclass]: chose IMKInputSession_Modern
2024-11-21 23:01:42.414 Electron[69539:715519] MacosNotificationState: FocusStatusCenter API available
2024-11-21 23:01:42.446 Electron[69539:715519] MacosNotificationState: promise created
/Users/tobias/Development/repositories/github/stretchly/node_modules/electron/dist/Electron.app/Contents/MacOS/Electron exited with signal SIGABRT

dev:
cross-env NODE_ENV=development electron . --trace-warnings --trace-deprecation --enable-logging --remote-debugging-port=9222

sh: /Users/devtobi/Development/repositories/github/stretchly/node_modules/.bin/cross-env: Permission denied

=> chmod -R a+x node_modules fixes this issue (but is this really the way to go?) and then again leads to same error as in start
lint has same permission error as in dev and is "fixed" by manually calling chmod on the binaries inside the node_modules folder.
@hovancik Are there any other npm scripts I should test?

Hi @devtobi , I don't have supported macbook, but I have latest macOS on my old macbook with https://dortania.github.io/OpenCore-Legacy-Patcher/, so this might not be absolutely relevant.
I don't ever remember having to do anything more that npm i on my macbook. Here is for example how I build the app for distribution on Github Actions: https://github.com/hovancik/stretchly/blob/trunk/.github/workflows/build.yml
For mac, I only make sure that command line tools are installed and then as you mention with newer python, i do `pip install setuptools.
If you updated your mac recently, I know it usually breaks the command line tools, so I had to remove them and install again after each OS upgrade.
But I do not use my macbook actively for many years now.

After reinstalling my command line tools the permission errors are gone and I do not have to chmod anymore. However the app still crashes instantly after launching either via start or dev.
I checked the Stretchly log file under /Library/Logs/Stretchly/main.log but nothing useful there.
Here is the whole log output when running npm run dev:

Log Output
DevTools listening on ws://<IP_ADDRESS>:9222/devtools/browser/88cdfd94-11f9-446c-82cd-46b737e920f8
12:33:47.990 › Stretchly: initializing...
12:33:47.997 › Stretchly: loading preferences
12:33:48.001 › Stretchly: starting Idle time monitoring
12:33:48.005 › Stretchly: starting Do Not Disturb monitoring
[60192:1123/123348.028392:WARNING:viz_main_impl.cc(85)] VizNullHypothesis is disabled (not a warning)
i18next: hasLoadedNamespace: i18next was not initialized undefined
i18next::translator: key "miniBreakIdeas" for languages "en" won't get resolved as namespace "translation" was not yet loaded This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!
i18next::translator: missingKey en translation miniBreakIdeas miniBreakIdeas
i18next::translator: missingKey undefined translation miniBreakIdeas.0.text miniBreakIdeas.0.text
i18next::translator: missingKey undefined translation miniBreakIdeas.1.text miniBreakIdeas.1.text
i18next::translator: missingKey undefined translation miniBreakIdeas.2.text miniBreakIdeas.2.text
i18next::translator: missingKey undefined translation miniBreakIdeas.3.text miniBreakIdeas.3.text
i18next::translator: missingKey undefined translation miniBreakIdeas.4.text miniBreakIdeas.4.text
i18next::translator: missingKey undefined translation miniBreakIdeas.5.text miniBreakIdeas.5.text
i18next::translator: missingKey undefined translation miniBreakIdeas.6.text miniBreakIdeas.6.text
i18next::translator: missingKey undefined translation miniBreakIdeas.7.text miniBreakIdeas.7.text
i18next::translator: missingKey undefined translation miniBreakIdeas.8.text miniBreakIdeas.8.text
i18next::translator: missingKey undefined translation miniBreakIdeas.9.text miniBreakIdeas.9.text
i18next::translator: missingKey undefined translation miniBreakIdeas.10.text miniBreakIdeas.10.text
i18next::translator: missingKey undefined translation miniBreakIdeas.11.text miniBreakIdeas.11.text
i18next::translator: missingKey undefined translation miniBreakIdeas.12.text miniBreakIdeas.12.text
i18next::translator: missingKey undefined translation miniBreakIdeas.13.text miniBreakIdeas.13.text
i18next::translator: missingKey en translation longBreakIdeas longBreakIdeas
i18next::translator: missingKey undefined translation longBreakIdeas.0.title longBreakIdeas.0.title
i18next::translator: missingKey undefined translation longBreakIdeas.0.text longBreakIdeas.0.text
i18next::translator: missingKey undefined translation longBreakIdeas.1.title longBreakIdeas.1.title
i18next::translator: missingKey undefined translation longBreakIdeas.1.text longBreakIdeas.1.text
i18next::translator: missingKey undefined translation longBreakIdeas.2.title longBreakIdeas.2.title
i18next::translator: missingKey undefined translation longBreakIdeas.2.text longBreakIdeas.2.text
i18next::translator: missingKey undefined translation longBreakIdeas.3.title longBreakIdeas.3.title
i18next::translator: missingKey undefined translation longBreakIdeas.3.text longBreakIdeas.3.text
i18next::translator: missingKey undefined translation longBreakIdeas.4.title longBreakIdeas.4.title
i18next::translator: missingKey undefined translation longBreakIdeas.4.text longBreakIdeas.4.text
i18next::translator: missingKey undefined translation longBreakIdeas.5.title longBreakIdeas.5.title
i18next::translator: missingKey undefined translation longBreakIdeas.5.text longBreakIdeas.5.text
i18next::translator: missingKey undefined translation longBreakIdeas.6.title longBreakIdeas.6.title
i18next::translator: missingKey undefined translation longBreakIdeas.6.text longBreakIdeas.6.text
i18next::translator: missingKey undefined translation longBreakIdeas.7.title longBreakIdeas.7.title
i18next::translator: missingKey undefined translation longBreakIdeas.7.text longBreakIdeas.7.text
i18next::translator: missingKey undefined translation longBreakIdeas.8.title longBreakIdeas.8.title
i18next::translator: missingKey undefined translation longBreakIdeas.8.text longBreakIdeas.8.text
i18next::translator: missingKey undefined translation longBreakIdeas.9.title longBreakIdeas.9.title
i18next::translator: missingKey undefined translation longBreakIdeas.9.text longBreakIdeas.9.text
i18next::translator: missingKey undefined translation longBreakIdeas.10.title longBreakIdeas.10.title
i18next::translator: missingKey undefined translation longBreakIdeas.10.text longBreakIdeas.10.text
i18next::translator: missingKey undefined translation longBreakIdeas.11.title longBreakIdeas.11.title
i18next::translator: missingKey undefined translation longBreakIdeas.11.text longBreakIdeas.11.text
i18next::translator: missingKey undefined translation longBreakIdeas.12.title longBreakIdeas.12.title
i18next::translator: missingKey undefined translation longBreakIdeas.12.text longBreakIdeas.12.text
i18next::translator: missingKey undefined translation longBreakIdeas.13.title longBreakIdeas.13.title
i18next::translator: missingKey undefined translation longBreakIdeas.13.text longBreakIdeas.13.text
12:33:48.114 › Stretchly: loading default break ideas
i18next::translator: missingKey undefined translation main.toolTipHeader main.toolTipHeader
i18next::translator: missingKey undefined translation statusMessages.nextMiniBreak statusMessages.nextMiniBreak
i18next::translator: missingKey undefined translation utils.inAbout utils.inAbout
i18next::translator: missingKey undefined translation statusMessages.nextLongBreak statusMessages.nextLongBreak
i18next::translator: missingKey undefined translation statusMessages.afterMiniBreak statusMessages.afterMiniBreak
i18next::translator: missingKey undefined translation statusMessages.nextMiniBreak statusMessages.nextMiniBreak
i18next::translator: missingKey undefined translation utils.inAbout utils.inAbout
i18next::translator: missingKey undefined translation statusMessages.nextLongBreak statusMessages.nextLongBreak
i18next::translator: missingKey undefined translation statusMessages.afterMiniBreak statusMessages.afterMiniBreak
i18next::translator: missingKey undefined translation main.toMicrobreak main.toMicrobreak
i18next::translator: missingKey undefined translation main.toBreak main.toBreak
i18next::translator: missingKey undefined translation main.skipToTheNext main.skipToTheNext
i18next::translator: missingKey undefined translation main.pause main.pause
i18next::translator: missingKey undefined translation utils.minutes utils.minutes
i18next::translator: missingKey undefined translation main.forHour main.forHour
i18next::translator: missingKey undefined translation main.for2Hours main.for2Hours
i18next::translator: missingKey undefined translation main.for5Hours main.for5Hours
i18next::translator: missingKey undefined translation main.untilMorning main.untilMorning
i18next::translator: missingKey undefined translation main.indefinitely main.indefinitely
i18next::translator: missingKey undefined translation main.resetBreaks main.resetBreaks
i18next::translator: missingKey undefined translation main.preferences main.preferences
i18next::translator: missingKey undefined translation main.quitStretchly main.quitStretchly
i18next::translator: missingKey en translation main.toolTipHeader main.toolTipHeader
i18next::translator: missingKey en translation statusMessages.nextMiniBreak statusMessages.nextMiniBreak
i18next::translator: missingKey en translation utils.inAbout utils.inAbout
i18next::translator: missingKey en translation statusMessages.nextLongBreak statusMessages.nextLongBreak
i18next::translator: missingKey en translation statusMessages.afterMiniBreak statusMessages.afterMiniBreak
i18next::translator: missingKey en translation statusMessages.nextMiniBreak statusMessages.nextMiniBreak
i18next::translator: missingKey en translation utils.inAbout utils.inAbout
i18next::translator: missingKey en translation statusMessages.nextLongBreak statusMessages.nextLongBreak
i18next::translator: missingKey en translation statusMessages.afterMiniBreak statusMessages.afterMiniBreak
i18next::translator: missingKey en translation main.toMicrobreak main.toMicrobreak
i18next::translator: missingKey en translation main.toBreak main.toBreak
i18next::translator: missingKey en translation main.skipToTheNext main.skipToTheNext
i18next::translator: missingKey en translation main.pause main.pause
i18next::translator: missingKey en translation utils.minutes utils.minutes
i18next::translator: missingKey en translation main.forHour main.forHour
i18next::translator: missingKey en translation main.for2Hours main.for2Hours
i18next::translator: missingKey en translation main.for5Hours main.for5Hours
i18next::translator: missingKey en translation main.untilMorning main.untilMorning
i18next::translator: missingKey en translation main.indefinitely main.indefinitely
i18next::translator: missingKey en translation main.resetBreaks main.resetBreaks
i18next::translator: missingKey en translation main.preferences main.preferences
i18next::translator: missingKey en translation main.quitStretchly main.quitStretchly
i18next::backendConnector: loaded namespace translation for language en {
  main: {
    toolTipHeader: 'Stretchly - The break time reminder app',
    microbreakIn: "Mini Break in $t(utils.seconds, {'count': {{seconds}} })",
    breakIn: "Long Break in $t(utils.seconds, {'count': {{seconds}} })",
    resumingBreaks: 'Resuming breaks',
    downloadLatestVersion: 'Download latest version',
    toBreak: 'Long Break',
    toMicrobreak: 'Mini Break',
    skipToTheNext: 'Skip to the next',
    resume: 'Resume Breaks',
    pause: 'Pause Breaks',
    forHour: '1 hour',
    for2Hours: '2 hours',
    for5Hours: '5 hours',
    untilMorning: 'Until morning',
    indefinitely: 'Indefinitely',
    resetBreaks: 'Reset Breaks',
    quitStretchly: 'Quit Stretchly',
    restoreDefaults: 'Restore defaults',
    warning: 'This will restore app defaults and all your settings will be lost.',
    continue: 'Continue',
    cancel: 'Cancel',
    preferences: 'Preferences',
    contributorPreferences: 'Contributor Preferences',
    syncPreferences: 'Sync Preferences'
  },
  break: {
    postpone: 'Postpone this break',
    skip: 'Skip this break',
    title: 'Time to take a break!'
  },
  preferences: {
    title: 'Stretchly Preferences',
    nav: {
      settings: 'Settings',
      schedule: 'Schedule',
      theme: 'Theme',
      about: 'About',
      heart: 'Love Stretchly'
    },
    settings: {
      openAtLogin: 'Start Stretchly automatically when logging in',
      showBreaksIn: 'Shows breaks in:',
      window: 'Window',
      fullscreen: 'Full screen',
      showIdeas: 'Show exercise tips during breaks',
      allScreens: 'Shows breaks on all monitors',
      monitorIdleTime: 'Monitor system idle time (breaks are paused if system is idle).',
      monitorDnd: 'Show breaks even in Do Not Disturb mode',
      language: 'Select language:',
      restoreDefaults: 'Restore defaults'
    },
    schedule: {
      miniBreaks: 'Mini Breaks:',
      miniBreaksInfo: 'Mini Breaks are short breaks taken regularly to give you a chance to stretch and relax.',
      enableMiniBreaks: 'Enable Mini Breaks',
      breakFor: 'Break for:',
      every: 'Every:',
      showNotificationBeforeMiniBreak: 'Show notification before Mini Break starts',
      enablePostponeMini: 'Enable Postponement for Mini Break',
      longBreaks: 'Long Breaks:',
      longBreaksInfo: 'Long Breaks are taken less regularly, but are of greater duration, allowing you to take an extended break from your work.',
      enableLongBreaks: 'Enable Long Breaks',
      showNotificationBeforeLongBreak: 'Show notification before Long Break starts',
      enablePostponeLong: 'Enable Postponement for Long Break',
      strictMode: 'Strict Mode:',
      strictModeInfo: 'Strict Mode prevents you from skipping either Mini Breaks or Long Breaks and is designed to help discipline.',
      enableStrictMini: 'Enable Strict Mode for Mini Breaks',
      enableStrictLong: 'Enable Strict Mode for Long Breaks',
      cantDisableBoth: 'It is not possible to disable both types of breaks'
    },
    theme: {
      appearance: 'Appearance:',
      greenClouds: 'Green clouds',
      autumnBeBlessed: 'Autumn be blessed',
      graphiteCrystal: 'Graphite crystal',
      coffeeKisses: 'Coffee kisses',
      morningSwim: 'Morning swim',
      transparentMode: 'Enable transparency',
      sounds: 'Sounds:',
      enableSounds: 'Enable sounds',
      crystalGlass: 'Crystal glass',
      windChime: 'Wind chime',
      ticToc: 'Tic toc',
      reverie: 'Reverie',
      menubarIcon: 'Menubar icon:',
      colour: 'Colour',
      monochrome: 'Monochrome',
      invertedMonochrome: 'Inverted Monochrome',
      snowWhite: 'Snow white'
    },
    about: {
      tagline: 'The break time reminder app',
      version: 'Version ',
      latestVersion: 'Latest version ',
      checkNewVersion: 'Automatically check for app updates',
      learnMore: 'To learn more about Stretchly features, view a tutorial, download the latest version or contact us for support, ',
      ourWebsite: 'visit our website',
      dot: '.',
      developedBy: 'Developed by',
      janH: 'Jan Hovancik',
      designedBy: 'Icon and UI design by Colin Shanley'
    },
    heart: {
      loveStretchly: 'Love your Stretchly?',
      desc1: 'Taking regular breaks when using a computer is scientifically proven to be important for your physical and mental well-being.',
      desc2: 'Stretchly is free. But you can lend your support by donating and help us continue to improve Stretchly and release other free software.',
      becomePatron: 'Become a Patron',
      alreadyContributor: "I'm already a contributor",
      authenticateUsing: 'Authenticate using:',
      contributorPreferences: 'Contributor Preferences',
      syncPreferences: 'Sync Preferences'
    }
  },
  contributorPreferences: {
    '0': 'First monitor',
    '1': 'Second monitor',
    '2': 'Third monitor',
    '3': 'Fourth monitor',
    '4': 'Fifth monitor',
    title: 'Contributor Preferences',
    notifications: 'Break notifications:',
    notificationsInfo: 'System notification shown before breaks to let you prepare for it.',
    beforeLongBreak: 'Long Break:',
    beforeMiniBreak: 'Mini Break:',
    newVersion: 'New version:',
    newVersionNotification: 'Notify when new version is available',
    customIdeas: 'Custom ideas:',
    customIdeasInfo: 'Allows you to use custom break ideas by editing configuration file. (For advanced users.)',
    useIdeasFromSettings: 'Use break ideas from configuration file',
    breakPostpone: 'Postponement of breaks:',
    breakPostponeInfo: 'If enabled in main Preferences, you can postpone breaks. Following settings allow you to specify when, for how long and how many times you can postpone a break.',
    miniBreaks: 'Mini Breaks:',
    postponableFor: 'Postponable for:',
    postponeFor: 'Postpone for:',
    maxPostpones: 'Max of postpones:',
    longBreaks: 'Long Breaks:',
    pauseUntilMoring: 'Pause until morning:',
    pauseUntil: 'Pause until:',
    pauseUntilMorningInfo: "Specify till what hour 'Pause until morning' should pause.",
    welcomeWindow: 'Welcome window:',
    showWelcomeWindow: 'Show Welcome window on next start',
    opacityTheme: 'Theme transparency:',
    opacityInfo: 'How solid should the break window be?',
    opacity: 'Opacity:',
    breakWindowSize: 'Break window size',
    breakWindowSizeInfo: 'What percentage of the screen should the break window hide?',
    breakWindowWidth: 'Width:',
    breakWindowHeight: 'Height:',
    sounds: 'Sounds:',
    volume: 'Volume:',
    miniBreakStartSound: 'Play end-of-break sound also at the start of Mini break',
    longBreakStartSound: 'Play end-of-break sound also at the start of Long break',
    naturalBreaks: 'Natural breaks:',
    naturalBreaksInfo: 'If monitoring of idle time is enabled in main Preferences, you can specify after what time the breaks should be paused.',
    pauseAfter: 'Pause after:',
    appearance: 'Appearance:',
    light: 'Light',
    dark: 'Dark',
    system: 'System',
    showBreaksAsRegularWindowsTitle: 'Act as regular window:',
    showBreaksAsRegularWindowsInfo: "When enabled, Break windows will become focusable, they won't be 'Always on top' anymore and they will also appear in the taskbar.",
    showBreaksAsRegularWindows: 'Show breaks as regular windows',
    screen: 'Monitor for Breaks:',
    screenInfo: 'When showing breaks on all monitors is disabled, you can choose which one you would like to show your Breaks on.',
    showOnMonitor: 'Show Breaks on',
    primary: 'Primary monitor',
    cursor: 'Follow cursor',
    timeToBreakInTray: 'Time to break',
    showTimeToBreakInTray: 'Show time to the next break in menubar icon',
    showTrayIcon: 'Show menubar icon',
    toShowTrayIcon: 'Show Stretchly icon in menubar',
    currentTimeInBreaks: 'Current time',
    showCurrentTimeInBreaks: 'Show current local time in break window'
  },
  utils: {
    remaining: '{{count}} remaining',
    inAbout: 'in about {{count}}',
    none_one: '{{count}}',
    none_other: '{{count}}',
    percent_one: '{{count}} percent',
    percent_other: '{{count}} percent',
    oclock_one: "{{count}} o'clock",
    oclock_other: "{{count}} o'clock",
    seconds_one: '{{count}} second',
    seconds_other: '{{count}} seconds',
    minutes_one: '{{count}} minute',
    minutes_other: '{{count}} minutes',
    hours_one: '{{count}} hour',
    hours_other: '{{count}} hours'
  },
  process: { newVersionAvailable: 'New version is available!' },
  welcome: {
    title: 'Welcome to Stretchly',
    breakTimeReminderApp: 'The break time reminder app',
    viewTutorial: 'View Tutorial',
    openPreferences: 'Open Preferences',
    getStarted: 'Get Started'
  },
  statusMessages: {
    paused: 'Paused',
    indefinitely: 'Indefinitely',
    dndMode: 'Do Not Disturb is on',
    appExclusion: 'App exclusion rule',
    nextLongBreak: 'Next Long Break',
    nextMiniBreak: 'Next Mini Break',
    afterMiniBreak_one: 'after {{count}} Mini Break',
    afterMiniBreak_other: 'after {{count}} Mini Breaks',
    resuming: 'Resuming'
  },
  miniBreakIdeas: {
    aaa: { text: 'Go grab a glass of water.' },
    aab: { text: 'Slowly look all the way left, then right.' },
    aac: { text: 'Slowly look all the way up, then down.' },
    aad: { text: 'Close your eyes and take few deep breaths.' },
    aae: { text: 'Close your eyes and relax.' },
    aaf: { text: 'Stretch your legs.' },
    aag: { text: 'Stretch your arms.' },
    aah: { text: 'Is your sitting posture correct?' },
    aai: { text: 'Slowly turn head to side and hold for 10 seconds.' },
    aaj: { text: 'Slowly tilt head to side and hold for 5-10 seconds.' },
    aak: { text: 'Stand from your chair and stretch.' },
    aal: { text: 'Refocus your eyes on an object at least 20 meters away.' },
    aam: { text: 'Take a moment to think about something you appreciate.' },
    aan: { text: 'Take a moment to smile at being alive.' },
    aao: {
      text: 'A truly ergonomic workstation is one that you regularly push away from.'
    },
    aap: { text: 'Close your eyes and count your breaths.' },
    aaq: { text: 'Close your eyes and name the things you hear.' },
    aar: {
      text: 'Place your fingertips on your shoulders. Roll your shoulders forward for 10 seconds, then backward.'
    },
    aas: {
      text: 'Raise your right arm, stretch it over your head to the left, and hold for 10 seconds. Repeat on the other side.'
    },
    aat: {
      text: 'With your right hand, grab each finger of your left hand in turn and squeeze. Repeat on the other side.'
    },
    aau: {
      text: 'Stand up and do a lunge. Hold for 10 seconds, then do the other leg.'
    },
    aav: {
      text: 'Close your eyes and simply notice whatever arises in current moment, without judgement.'
    },
    aaw: {
      text: 'Focus every 20 minutes for 20 seconds on an object at 20 feet distance.'
    },
    aax: { text: 'If you need help, ask for it.' },
    aay: { text: 'Do one thing at a time.' },
    aaz: { text: 'Is your attention spent wisely?' },
    aba: { text: 'Change your sitting posture.' },
    abb: { text: 'Expose your eyes to natural light.' },
    abc: {
      text: 'With your eyes closed, slowly and gently raise your eyes to the ceiling and back down to the floor.'
    },
    abd: {
      text: 'With your eyes closed, slowly and gently move your eyes to the left, then slowly to the right.'
    },
    abe: { text: 'Shake your hands out to get some relief.' },
    abf: {
      text: 'One at a time, touch the tip of each finger to the tip of your thumb so they make an O-shape.'
    },
    abg: {
      text: "Make a fist and then slide your fingers up until they point toward the ceiling, like you're telling someone to stop."
     Squeeze your shoulder blades together and hold.'
    },
    abl: {
      text: 'Stand tall with your arms raised along your shoulders. Move hands slightly behind your back, hold for a second and return.'
    },
    abm: {
      text: 'Sit on the edge of your chair, twist your torso to one side and hold for 10-15 seconds. Repeat on the other side.'
    },
    abn: {
      text: 'Stand up and put one foot on a nearby object, like a chair or step stool. Keep your knee bent and hold for 10-15 seconds.   Repeat with the other leg.'
    },
    abs: {
      text: 'Stand facing a wall, put one foot back and the other foot forward, then lean into the wall.  Hold for 10-15 seconds. Repeat with the other arm.'
    },
    abu: {
      text: 'Tilt your head to one side, then to the other side, and then gently tilt it forward and backward.'
    },
    abv: {
      text: 'Reach one arm across your chest, hold onto the elbow with the other hand, and gently pull it in towards your chest. Repeat with the other arm.'
    },
    abw: {
      text: 'Stand up, put one foot on a nearby object, like a chair or step stool, and reach down to touch your toes. Repeat with the other leg.'
    },
    abx: {
      text: 'Stand in a doorway and place one arm on each side of the doorway, then gently lean forward until you feel a stretch in your chest.'
    },
    aby: {
      text: 'Sit on the edge of a chair or on the floor, and place the soles of your feet together, gently pressing down with your elbows to stretch your inner thighs.'
    }
  },
  longBreakIdeas: {
    aaa: {
      title: 'Not alone',
      text: 'Do you find it hard to take a break alone? Try to do it with a co-worker. Aside from making it easier to stick to breaks, you will have a chance to get to know them better. Taking breaks together increases productivity.'
    },
    aab: {
      title: 'Step away',
      text: 'Do you ever notice how your brain can figure things out by itself? All it takes is to step away from the computer and take a break to think about something totally unrelated.'
    },
    aac: {
      title: 'Microbreaks',
      text: 'Rest is a key component in ensuring the performance of the musculoskeletal system. Frequent breaks can decrease the duration of a task and help lower the exposure to ergonomic injury risk.'
    },
    aad: {
      title: 'Meditation',
      text: 'Research studies suggest that mindfulness-based exercises help decrease anxiety, depression, stress, and pain, and help improve general health, mental health, and quality of life. Not sure how to start? There are numerous apps to help you out.'
    },
    aae: {
      title: 'Blink',
      text: 'Looking at screens for a long time causes you to blink less, thus exposing your eyes to the air. Blink rapidly for a few secondsto refresh the tear film and clear dust from the eye surface.'
    },
    aaf: {
      title: 'Ergonomics',
      text: 'Improper height and angle of the keyboard, mouse, monitor or working surface can cause health problems. Take some time to read about desk ergonomics.'
    },
    aag: {
      title: 'Move',
      text: 'There are a lot of ways you can exercise within your office. Try marching in place or doing desk push-ups.'
    },
    aah: {
      title: 'Change',
      text: 'Do you have a stability ball or standing work desk?  It is a sign that you need to take a break.'
    },
    aaj: { title: 'Tech', text: 'How about taking a no-tech walk?' },
    aak: {
      title: 'Metabolism',
      text: 'Emerging research shows that sitting for long periods of time contributes to risk of metabolic syndrome, heart attack and strokerisk and overall death risk, among others. Taking regular walking breaks can help your circulation, working to counteract some of those problems.'
    },
    aal: {
      title: 'Active Meetings',
      text: 'How about moving meetings from the conference room to the concourse? Walking not only burns calories but it may even foster a sense of collaboration.'
    },
    aam: {
      title: 'Fruit',
      text: 'Take your time and eat some fruit. Slowly. Notice the flavor, the texture, the freshness.'
    },
    aan: {
      title: 'Bathrooms',
      text: 'Walk to the farthest bathroom in the worksite facility when going to the restroom.'
    },
    aao: {
      title: 'Coffee break',
      text: 'Going on coffee break? Consider doing a 5-minute walk every time you go for one.'
    },
    aap: {
      title: 'Colleagues',
      text: 'Do not email or message office colleagues, walk to their desks to communicate with them.'
    },
    aaq: {
      title: 'Learning',
      text: 'In a study of healthy volunteers, NIH researchers found that taking short breaks, early and often, may help our brains learn newskills.'
    },
    aar: {
      title: 'Exercise',
      text: 'Evidence suggests small amounts of regular exercise can bring dramatic health benefits, including measurably reducing stress.'
    },
    aas: {
      title: 'Repeat',
      text: 'Have you found your stretch-ly-routine? Do not forget to repeat it for more than once to better fight effects of prolonged sitting.'
    },
    aat: {
      title: 'Wrist and forearm',
      text: 'Extend your arms with the palms facing towards you, then slowly rotate the hands four times clockwise, then four times counter-clockwise.'
    },
    aau: {
      title: 'Back stretching',
      text: 'Join your hands behind your head, then lift them together up above your head ending with your palms facing upward.'
    },
    aav: {
      title: 'Mobilize',
      text: 'For every thirty minutes of stagnation, you should have at least one minute of stimulation.'
    },
    aaw: {
      title: '7 Minute Workout',
      text: 'This workout packs in a full-body exercise routine in a fraction of the time. But as with any exercise, be careful. There are numerous apps to get you started.'
    },
    aax: {
      title: 'Pulse',
      text: 'Raise your pulse rate to 120 beats per minute for 20 straight minutes four or five times a week doing anything you enjoy. Regularly raising your heart rate results in improved cardiovascular health.'
    },
    aay: {
      title: 'Take the stairs',
      text: 'Studies have shown that stair climbing, which is considered vigorous-intensity physical activity, burns more calories per minutethan jogging.'
    },
    aaz: {
      title: 'Make art',
      text: 'Art therapy is known to have great mental health benefits, especially when it comes to stress management. How about writing a quick poem, taking a picture or painting something small?'
    },
    aba: {
      title: 'Declutter',
      text: 'A clean space helps your focus at work and is often linked to positive emotions like happiness.'
    },
    abb: {
      title: 'Lunch outside',
      text: 'Nature is linked to positive emotions and decreased stress and anxiety. Whenever possible, try to take your daily lunch break outside, surrounded by some greenery.'
    },
    abc: {
      title: 'Public transport',
      text: 'If you use public transport regularly, you can stand instead of sitting. If it is possible, try to replace as many of your dailytrips as possible with walking or cycling.'
    },
    abd: {
      title: 'Yawning',
      text: 'Yawning can be really helpful, as it produces tears to help moisten and lubricate the eyes.'
    },
    abe: {
      title: 'Focus change',
      text: 'Hold one finger close to the eye and focus on it. Slowly move the finger away, focus far into the distance and then back to the finger. Bring the finger back and focus on something far away.'
    },
    abf: {
      title: 'Palming',
      text: 'While seated, brace elbows on the desk and close to the desk edge. Let your weight fall forward and cup hands over eyes. Close your eyes and inhale slowly through nose and hold for few seconds. Continue deep breathing.'
    },
    abg: {
      title: 'Hand squeezes',
      text: 'Squeeze a pair of balled-up socks or a soft rubber ball, hold for 5 seconds. Repeat whole process a few times.'
    },
    abh: {
      title: 'Slow Breathing',
      text: 'Emerging research suggests potential for use of controlled slow breathing techniques as a means of optimising physiological parameters that appear to be associated with health and longevity.'
    },
    abi: {
      title: 'Imaginative visualization',
      text: 'Close your eyes and imagine yourself in a peaceful and calming place, such as a beach or a forest, focusing on the sights, sounds, and sensations of that environment.'
    }
  }
}
12:33:48.228 › Stretchly: loading default break ideas
i18next: languageChanged en
i18next: initialized {
  debug: true,
  initImmediate: true,
  ns: [ 'translation' ],
  defaultNS: [ 'translation' ],
  fallbackLng: [ 'en' ],
  fallbackNS: false,
  supportedLngs: false,
  nonExplicitSupportedLngs: false,
  load: 'all',
  preload: false,
  simplifyPluralSuffix: true,
  keySeparator: '.',
  nsSeparator: ':',
  pluralSeparator: '_',
  contextSeparator: '_',
  partialBundledLanguages: false,
  saveMissing: false,
  updateMissing: false,
  saveMissingTo: 'fallback',
  saveMissingPlurals: true,
  missingKeyHandler: false,
  missingInterpolationHandler: false,
  postProcess: false,
  postProcessPassResolved: false,
  returnNull: false,
  returnEmptyString: true,
  returnObjects: false,
  joinArrays: false,
  returnedObjectHandler: false,
  parseMissingKeyHandler: false,
  appendNamespaceToMissingKey: false,
  appendNamespaceToCIMode: false,
  overloadTranslationOptionHandler: [Function: overloadTranslationOptionHandler],
  interpolation: {
    escapeValue: true,
    format: [Function: bound format],
    prefix: '{{',
    suffix: '}}',
    formatSeparator: ',',
    unescapePrefix: '-',
    nestingPrefix: '$t(',
    nestingSuffix: ')',
    nestingOptionsSeparator: ',',
    maxReplaces: 1000,
    skipOnVariables: true
  },
  lng: 'en',
  backend: {
    loadPath: '/Users/tobias/Development/repositories/github/stretchly/app/locales/{{lng}}.json',
    jsonIndent: 2,
    addPath: '/locales/{{lng}}/{{ns}}.missing.json',
    ident: 2,
    parse: [Function: parse],
    stringify: [Function: stringify]
  },
  ignoreJSONStructure: true
}
2024-11-23 12:33:48.441 Electron[60191:302529] +[IMKClient subclass]: chose IMKClient_Modern
2024-11-23 12:33:48.441 Electron[60191:302529] +[IMKInputSession subclass]: chose IMKInputSession_Modern
2024-11-23 12:33:49.012 Electron[60191:302529] MacosNotificationState: FocusStatusCenter API available
2024-11-23 12:33:49.052 Electron[60191:302529] MacosNotificationState: promise created
/Users/tobias/Development/repositories/github/stretchly/node_modules/electron/dist/Electron.app/Contents/MacOS/Electron exited with signal SIGABRT

I doubled checked whether the currently released version of Stretchly also has those issues but everything works fine and this time no crashes appear. So its really just a development thing.
Even after running npm run pack and then trying to launch the generated .app file, it crashes. Do you have any clue what might cause this? Or any clue on how could dive deeper into debugging this? As already mentioned npm run dev does not produce useful information.

I am using the current state of the trunk branch. Might this be an issue?

I would try removing node_modules and running npm i -g npm to update npm and  npm i again.
Trying on my mac machine and all works fine

Already did that. Unfortunately it is still not working. 😟

Uf, at loss here. Maybe try running example electron app if that works?
https://github.com/electron/electron-quick-start

The electron example app works without any issues. I have a strong assumption it might be because Stretchly might be using the FocusStatusCenter API in electron and some kind of permissions missing. @hovancik Does Stretchly make use of this API inside its code?
See e.g. this comment https://github.com/ferdium/ferdium-app/issues/1892#issuecomment-2351607299 where someone reports crash issues when electron tries to access the focus status of the OS. Could this be the same cause?
I checked the Info.plist files and did not find NSFocusStatusUsageDescription there. However in the currently released version the key is not included there either so this might also not be the reason.
I even tried including the crashHandler of electron to get more debug output but this didn't help as well.
As far as I researched this SIGABRT errors in macOS often happen due to missing of certain usage descriptions.
@hovancik Can you confirm that you get
[20722:1125/000228.482909:WARNING:viz_main_impl.cc(85)] VizNullHypothesis is disabled (not a warning)
i18next: hasLoadedNamespace: i18next was not initialized undefined
i18next::translator: key "miniBreakIdeas" for languages "en" won't get resolved as namespace "translation" was not yet loaded This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!

as well when starting the app in development mode using the current trunk? This way I can exclude one more thing from the causes.
For some reason using npm run pack now produces an app that I can run without crashes. Not the most elegant solution for developing but might be a temporary solution.

This is my output:
➜  stretchly git:(trunk) npm run dev

><EMAIL_ADDRESS>dev
> cross-env NODE_ENV=development electron . --trace-warnings --trace-deprecation --enable-logging --remote-debugging-port=9222

DevTools listening on ws://<IP_ADDRESS>:9222/devtools/browser/24b22217-aab7-4be6-a094-0299d5e9a04d
19:29:50.683 › Stretchly: initializing...
19:29:50.709 › Stretchly: loading preferences
19:29:50.726 › Stretchly: starting Idle time monitoring
i18next: hasLoadedNamespace: i18next was not initialized undefined
i18next::translator: key "miniBreakIdeas" for languages "en" won't get resolved as namespace "translation" was not yet loaded This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!
i18next::translator: missingKey en translation miniBreakIdeas miniBreakIdeas
i18next::translator: missingKey undefined translation miniBreakIdeas.0.text miniBreakIdeas.0.text
i18next::translator: missingKey undefined translation miniBreakIdeas.1.text miniBreakIdeas.1.text
i18next::translator: missingKey undefined translation miniBreakIdeas.2.text miniBreakIdeas.2.text
i18next::translator: missingKey undefined translation miniBreakIdeas.3.text miniBreakIdeas.3.text
i18next::translator: missingKey undefined translation miniBreakIdeas.4.text miniBreakIdeas.4.text
i18next::translator: missingKey undefined translation miniBreakIdeas.5.text miniBreakIdeas.5.text
i18next::translator: missingKey undefined translation miniBreakIdeas.6.text miniBreakIdeas.6.text
i18next::translator: missingKey undefined translation miniBreakIdeas.7.text miniBreakIdeas.7.text
i18next::translator: missingKey undefined translation miniBreakIdeas.8.text miniBreakIdeas.8.text
i18next::translator: missingKey undefined translation miniBreakIdeas.9.text miniBreakIdeas.9.text
i18next::translator: missingKey undefined translation miniBreakIdeas.10.text miniBreakIdeas.10.text
i18next::translator: missingKey undefined translation miniBreakIdeas.11.text miniBreakIdeas.11.text
i18next::translator: missingKey undefined translation miniBreakIdeas.12.text miniBreakIdeas.12.text
i18next::translator: missingKey undefined translation miniBreakIdeas.13.text miniBreakIdeas.13.text
i18next::translator: missingKey en translation longBreakIdeas longBreakIdeas
i18next::translator: missingKey undefined translation longBreakIdeas.0.title longBreakIdeas.0.title
i18next::translator: missingKey undefined translation longBreakIdeas.0.text longBreakIdeas.0.text
i18next::translator: missingKey undefined translation longBreakIdeas.1.title longBreakIdeas.1.title
i18next::translator: missingKey undefined translation longBreakIdeas.1.text longBreakIdeas.1.text
i18next::translator: missingKey undefined translation longBreakIdeas.2.title longBreakIdeas.2.title
i18next::translator: missingKey undefined translation longBreakIdeas.2.text longBreakIdeas.2.text
i18next::translator: missingKey undefined translation longBreakIdeas.3.title longBreakIdeas.3.title
i18next::translator: missingKey undefined translation longBreakIdeas.3.text longBreakIdeas.3.text
i18next::translator: missingKey undefined translation longBreakIdeas.4.title longBreakIdeas.4.title
i18next::translator: missingKey undefined translation longBreakIdeas.4.text longBreakIdeas.4.text
i18next::translator: missingKey undefined translation longBreakIdeas.5.title longBreakIdeas.5.title
i18next::translator: missingKey undefined translation longBreakIdeas.5.text longBreakIdeas.5.text
i18next::translator: missingKey undefined translation longBreakIdeas.6.title longBreakIdeas.6.title
i18next::translator: missingKey undefined translation longBreakIdeas.6.text longBreakIdeas.6.text
i18next::translator: missingKey undefined translation longBreakIdeas.7.title longBreakIdeas.7.title
i18next::translator: missingKey undefined translation longBreakIdeas.7.text longBreakIdeas.7.text
i18next::translator: missingKey undefined translation longBreakIdeas.8.title longBreakIdeas.8.title
i18next::translator: missingKey undefined translation longBreakIdeas.8.text longBreakIdeas.8.text
i18next::translator: missingKey undefined translation longBreakIdeas.9.title longBreakIdeas.9.title
i18next::translator: missingKey undefined translation longBreakIdeas.9.text longBreakIdeas.9.text
i18next::translator: missingKey undefined translation longBreakIdeas.10.title longBreakIdeas.10.title
i18next::translator: missingKey undefined translation longBreakIdeas.10.text longBreakIdeas.10.text
i18next::translator: missingKey undefined translation longBreakIdeas.11.title longBreakIdeas.11.title
i18next::translator: missingKey undefined translation longBreakIdeas.11.text longBreakIdeas.11.text
i18next::translator: missingKey undefined translation longBreakIdeas.12.title longBreakIdeas.12.title
i18next::translator: missingKey undefined translation longBreakIdeas.12.text longBreakIdeas.12.text
i18next::translator: missingKey undefined translation longBreakIdeas.13.title longBreakIdeas.13.title
i18next::translator: missingKey undefined translation longBreakIdeas.13.text longBreakIdeas.13.text
19:29:51.091 › Stretchly: loading default break ideas
i18next::translator: missingKey undefined translation main.toolTipHeader main.toolTipHeader
i18next::translator: missingKey undefined translation statusMessages.nextMiniBreak statusMessages.nextMiniBreak
i18next::translator: missingKey undefined translation utils.inAbout utils.inAbout
i18next::translator: missingKey undefined translation statusMessages.nextLongBreak statusMessages.nextLongBreak
i18next::translator: missingKey undefined translation statusMessages.afterMiniBreak statusMessages.afterMiniBreak
i18next::translator: missingKey undefined translation statusMessages.nextMiniBreak statusMessages.nextMiniBreak
i18next::translator: missingKey undefined translation utils.inAbout utils.inAbout
i18next::translator: missingKey undefined translation statusMessages.nextLongBreak statusMessages.nextLongBreak
i18next::translator: missingKey undefined translation statusMessages.afterMiniBreak statusMessages.afterMiniBreak
i18next::translator: missingKey undefined translation main.toMicrobreak main.toMicrobreak
i18next::translator: missingKey undefined translation main.toBreak main.toBreak
i18next::translator: missingKey undefined translation main.skipToTheNext main.skipToTheNext
i18next::translator: missingKey undefined translation main.pause main.pause
i18next::translator: missingKey undefined translation utils.minutes utils.minutes
i18next::translator: missingKey undefined translation main.forHour main.forHour
i18next::translator: missingKey undefined translation main.for2Hours main.for2Hours
i18next::translator: missingKey undefined translation main.for5Hours main.for5Hours
i18next::translator: missingKey undefined translation main.untilMorning main.untilMorning
i18next::translator: missingKey undefined translation main.indefinitely main.indefinitely
i18next::translator: missingKey undefined translation main.resetBreaks main.resetBreaks
i18next::translator: missingKey undefined translation main.preferences main.preferences
i18next::translator: missingKey undefined translation main.quitStretchly main.quitStretchly
i18next::translator: missingKey en translation main.toolTipHeader main.toolTipHeader
i18next::translator: missingKey en translation statusMessages.nextMiniBreak statusMessages.nextMiniBreak
i18next::translator: missingKey en translation utils.inAbout utils.inAbout
i18next::translator: missingKey en translation statusMessages.nextLongBreak statusMessages.nextLongBreak
i18next::translator: missingKey en translation statusMessages.afterMiniBreak statusMessages.afterMiniBreak
i18next::translator: missingKey en translation statusMessages.nextMiniBreak statusMessages.nextMiniBreak
i18next::translator: missingKey en translation utils.inAbout utils.inAbout
i18next::translator: missingKey en translation statusMessages.nextLongBreak statusMessages.nextLongBreak
i18next::translator: missingKey en translation statusMessages.afterMiniBreak statusMessages.afterMiniBreak
i18next::translator: missingKey en translation main.toMicrobreak main.toMicrobreak
i18next::translator: missingKey en translation main.toBreak main.toBreak
i18next::translator: missingKey en translation main.skipToTheNext main.skipToTheNext
i18next::translator: missingKey en translation main.pause main.pause
i18next::translator: missingKey en translation utils.minutes utils.minutes
i18next::translator: missingKey en translation main.forHour main.forHour
i18next::translator: missingKey en translation main.for2Hours main.for2Hours
i18next::translator: missingKey en translation main.for5Hours main.for5Hours
i18next::translator: missingKey en translation main.untilMorning main.untilMorning
i18next::translator: missingKey en translation main.indefinitely main.indefinitely
i18next::translator: missingKey en translation main.resetBreaks main.resetBreaks
i18next::translator: missingKey en translation main.preferences main.preferences
i18next::translator: missingKey en translation main.quitStretchly main.quitStretchly
i18next::backendConnector: loaded namespace translation for language en {
  main: {
    toolTipHeader: 'Stretchly - The break time reminder app',
    microbreakIn: "Mini Break in $t(utils.seconds, {'count': {{seconds}} })",
    breakIn: "Long Break in $t(utils.seconds, {'count': {{seconds}} })",
    resumingBreaks: 'Resuming breaks',
    downloadLatestVersion: 'Download latest version',
    toBreak: 'Long Break',
    toMicrobreak: 'Mini Break',
    skipToTheNext: 'Skip to the next',
    resume: 'Resume Breaks',
    pause: 'Pause Breaks',
    forHour: '1 hour',
    for2Hours: '2 hours',
    for5Hours: '5 hours',
    untilMorning: 'Until morning',
    indefinitely: 'Indefinitely',
    resetBreaks: 'Reset Breaks',
    quitStretchly: 'Quit Stretchly',
    restoreDefaults: 'Restore defaults',
    warning: 'This will restore app defaults and all your settings will be lost.',
    continue: 'Continue',
    cancel: 'Cancel',
    preferences: 'Preferences',
    contributorPreferences: 'Contributor Preferences',
    syncPreferences: 'Sync Preferences'
  },
  break: {
    postpone: 'Postpone this break',
    skip: 'Skip this break',
    title: 'Time to take a break!'
  },
  preferences: {
    title: 'Stretchly Preferences',
    nav: {
      settings: 'Settings',
      schedule: 'Schedule',
      theme: 'Theme',
      about: 'About',
      heart: 'Love Stretchly'
    },
    settings: {
      openAtLogin: 'Start Stretchly automatically when logging in',
      showBreaksIn: 'Shows breaks in:',
      window: 'Window',
      fullscreen: 'Full screen',
      showIdeas: 'Show exercise tips during breaks',
      allScreens: 'Shows breaks on all monitors',
      monitorIdleTime: 'Monitor system idle time (breaks are paused if system is idle).',
      monitorDnd: 'Show breaks even in Do Not Disturb mode',
      language: 'Select language:',
      restoreDefaults: 'Restore defaults'
    },
    schedule: {
      miniBreaks: 'Mini Breaks:',
      miniBreaksInfo: 'Mini Breaks are short breaks taken regularly to give you a chance to stretch and relax.',
      enableMiniBreaks: 'Enable Mini Breaks',
      breakFor: 'Break for:',
      every: 'Every:',
      showNotificationBeforeMiniBreak: 'Show notification before Mini Break starts',
      enablePostponeMini: 'Enable Postponement for Mini Break',
      longBreaks: 'Long Breaks:',
      longBreaksInfo: 'Long Breaks are taken less regularly, but are of greater duration, allowing you to take an extended break from your work.',
      enableLongBreaks: 'Enable Long Breaks',
      showNotificationBeforeLongBreak: 'Show notification before Long Break starts',
      enablePostponeLong: 'Enable Postponement for Long Break',
      strictMode: 'Strict Mode:',
      strictModeInfo: 'Strict Mode prevents you from skipping either Mini Breaks or Long Breaks and is designed to help discipline.',
      enableStrictMini: 'Enable Strict Mode for Mini Breaks',
      enableStrictLong: 'Enable Strict Mode for Long Breaks',
      cantDisableBoth: 'It is not possible to disable both types of breaks'
    },
    theme: {
      appearance: 'Appearance:',
      greenClouds: 'Green clouds',
      autumnBeBlessed: 'Autumn be blessed',
      graphiteCrystal: 'Graphite crystal',
      coffeeKisses: 'Coffee kisses',
      morningSwim: 'Morning swim',
      transparentMode: 'Enable transparency',
      sounds: 'Sounds:',
      enableSounds: 'Enable sounds',
      crystalGlass: 'Crystal glass',
      windChime: 'Wind chime',
      ticToc: 'Tic toc',
      reverie: 'Reverie',
      menubarIcon: 'Menubar icon:',
      colour: 'Colour',
      monochrome: 'Monochrome',
      invertedMonochrome: 'Inverted Monochrome',
      snowWhite: 'Snow white'
    },
    about: {
      tagline: 'The break time reminder app',
      version: 'Version ',
      latestVersion: 'Latest version ',
      checkNewVersion: 'Automatically check for app updates',
      learnMore: 'To learn more about Stretchly features, view a tutorial, download the latest version or contact us for support, ',
      ourWebsite: 'visit our website',
      dot: '.',
      developedBy: 'Developed by',
      janH: 'Jan Hovancik',
      designedBy: 'Icon and UI design by Colin Shanley'
    },
    heart: {
      loveStretchly: 'Love your Stretchly?',
      desc1: 'Taking regular breaks when using a computer is scientifically proven to be important for your physical and mental well-being.',
      desc2: 'Stretchly is free. But you can lend your support by donating and help us continue to improve Stretchly and release other free software.',
      becomePatron: 'Become a Patron',
      alreadyContributor: "I'm already a contributor",
      authenticateUsing: 'Authenticate using:',
      contributorPreferences: 'Contributor Preferences',
      syncPreferences: 'Sync Preferences'
    }
  },
  contributorPreferences: {
    '0': 'First monitor',
    '1': 'Second monitor',
    '2': 'Third monitor',
    '3': 'Fourth monitor',
    '4': 'Fifth monitor',
    title: 'Contributor Preferences',
    notifications: 'Break notifications:',
    notificationsInfo: 'System notification shown before breaks to let you prepare for it.',
    beforeLongBreak: 'Long Break:',
    beforeMiniBreak: 'Mini Break:',
    newVersion: 'New version:',
    newVersionNotification: 'Notify when new version is available',
    customIdeas: 'Custom ideas:',
    customIdeasInfo: 'Allows you to use custom break ideas by editing configuration file. (For advanced users.)',
    useIdeasFromSettings: 'Use break ideas from configuration file',
    breakPostpone: 'Postponement of breaks:',
    breakPostponeInfo: 'If enabled in main Preferences, you can postpone breaks. Following settings allow you to specify when, for how long and how many times you can postpone a break.',
    miniBreaks: 'Mini Breaks:',
    postponableFor: 'Postponable for:',
    postponeFor: 'Postpone for:',
    maxPostpones: 'Max of postpones:',
    longBreaks: 'Long Breaks:',
    pauseUntilMoring: 'Pause until morning:',
    pauseUntil: 'Pause until:',
    pauseUntilMorningInfo: "Specify till what hour 'Pause until morning' should pause.",
    welcomeWindow: 'Welcome window:',
    showWelcomeWindow: 'Show Welcome window on next start',
    opacityTheme: 'Theme transparency:',
    opacityInfo: 'How solid should the break window be?',
    opacity: 'Opacity:',
    breakWindowSize: 'Break window size',
    breakWindowSizeInfo: 'What percentage of the screen should the break window hide?',
    breakWindowWidth: 'Width:',
    breakWindowHeight: 'Height:',
    sounds: 'Sounds:',
    volume: 'Volume:',
    miniBreakStartSound: 'Play end-of-break sound also at the start of Mini break',
    longBreakStartSound: 'Play end-of-break sound also at the start of Long break',
    naturalBreaks: 'Natural breaks:',
    naturalBreaksInfo: 'If monitoring of idle time is enabled in main Preferences, you can specify after what time the breaks should be paused.',
    pauseAfter: 'Pause after:',
    appearance: 'Appearance:',
    light: 'Light',
    dark: 'Dark',
    system: 'System',
    showBreaksAsRegularWindowsTitle: 'Act as regular window:',
    showBreaksAsRegularWindowsInfo: "When enabled, Break windows will become focusable, they won't be 'Always on top' anymore and they will also appear in the taskbar.",
    showBreaksAsRegularWindows: 'Show breaks as regular windows',
    screen: 'Monitor for Breaks:',
    screenInfo: 'When showing breaks on all monitors is disabled, you can choose which one you would like to show your Breaks on.',
    showOnMonitor: 'Show Breaks on',
    primary: 'Primary monitor',
    cursor: 'Follow cursor',
    timeToBreakInTray: 'Time to break',
    showTimeToBreakInTray: 'Show time to the next break in menubar icon',
    showTrayIcon: 'Show menubar icon',
    toShowTrayIcon: 'Show Stretchly icon in menubar',
    currentTimeInBreaks: 'Current time',
    showCurrentTimeInBreaks: 'Show current local time in break window'
  },
  utils: {
    remaining: '{{count}} remaining',
    inAbout: 'in about {{count}}',
    none_one: '{{count}}',
    none_other: '{{count}}',
    percent_one: '{{count}} percent',
    percent_other: '{{count}} percent',
    oclock_one: "{{count}} o'clock",
    oclock_other: "{{count}} o'clock",
    seconds_one: '{{count}} second',
    seconds_other: '{{count}} seconds',
    minutes_one: '{{count}} minute',
    minutes_other: '{{count}} minutes',
    hours_one: '{{count}} hour',
    hours_other: '{{count}} hours'
  },
  process: { newVersionAvailable: 'New version is available!' },
  welcome: {
    title: 'Welcome to Stretchly',
    breakTimeReminderApp: 'The break time reminder app',
    viewTutorial: 'View Tutorial',
    openPreferences: 'Open Preferences',
    getStarted: 'Get Started'
  },
  statusMessages: {
    paused: 'Paused',
    indefinitely: 'Indefinitely',
    dndMode: 'Do Not Disturb is on',
    appExclusion: 'App exclusion rule',
    nextLongBreak: 'Next Long Break',
    nextMiniBreak: 'Next Mini Break',
    afterMiniBreak_one: 'after {{count}} Mini Break',
    afterMiniBreak_other: 'after {{count}} Mini Breaks',
    resuming: 'Resuming'
  },
  miniBreakIdeas: {
    aaa: { text: 'Go grab a glass of water.' },
    aab: { text: 'Slowly look all the way left, then right.' },
    aac: { text: 'Slowly look all the way up, then down.' },
    aad: { text: 'Close your eyes and take few deep breaths.' },
    aae: { text: 'Close your eyes and relax.' },
    aaf: { text: 'Stretch your legs.' },
    aag: { text: 'Stretch your arms.' },
    aah: { text: 'Is your sitting posture correct?' },
    aai: { text: 'Slowly turn head to side and hold for 10 seconds.' },
    aaj: { text: 'Slowly tilt head to side and hold for 5-10 seconds.' },
    aak: { text: 'Stand from your chair and stretch.' },
    aal: { text: 'Refocus your eyes on an object at least 20 meters away.' },
    aam: { text: 'Take a moment to think about something you appreciate.' },
    aan: { text: 'Take a moment to smile at being alive.' },
    aao: {
      text: 'A truly ergonomic workstation is one that you regularly push away from.'
    },
    aap: { text: 'Close your eyes and count your breaths.' },
    aaq: { text: 'Close your eyes and name the things you hear.' },
    aar: {
      text: 'Place your fingertips on your shoulders. Roll your shoulders forward for 10 seconds, then backward.'
    },
    aas: {
      text: 'Raise your right arm, stretch it over your head to the left, and hold for 10 seconds. Repeat on the other side.'
    },
    aat: {
      text: 'With your right hand, grab each finger of your left hand in turn and squeeze. Repeat on the other side.'
    },
    aau: {
      text: 'Stand up and do a lunge. Hold for 10 seconds, then do the other leg.'
    },
    aav: {
      text: 'Close your eyes and simply notice whatever arises in current moment, without judgement.'
    },
    aaw: {
      text: 'Focus every 20 minutes for 20 seconds on an object at 20 feet distance.'
    },
    aax: { text: 'If you need help, ask for it.' },
    aay: { text: 'Do one thing at a time.' },
    aaz: { text: 'Is your attention spent wisely?' },
    aba: { text: 'Change your sitting posture.' },
    abb: { text: 'Expose your eyes to natural light.' },
    abc: {
      text: 'With your eyes closed, slowly and gently raise your eyes to the ceiling and back down to the floor.'
    },
    abd: {
      text: 'With your eyes closed, slowly and gently move your eyes to the left, then slowly to the right.'
    },
    abe: { text: 'Shake your hands out to get some relief.' },
    abf: {
      text: 'One at a time, touch the tip of each finger to the tip of your thumb so they make an O-shape.'
    },
    abg: {
      text: "Make a fist and then slide your fingers up until they point toward the ceiling, like you're telling someone to stop."
     Squeeze your shoulder blades together and hold.'
    },
    abl: {
      text: 'Stand tall with your arms raised along your shoulders. Move hands slightly behind your back, hold for a second and return.'
    },
    abm: {
      text: 'Sit on the edge of your chair, twist your torso to one side and hold for 10-15 seconds. Repeat on the other side.'
    },
    abn: {
      text: 'Stand up and put one foot on a nearby object, like a chair or step stool. Keep your knee bent and hold for 10-15 seconds.   Repeat with the other leg.'
    },
    abs: {
      text: 'Stand facing a wall, put one foot back and the other foot forward, then lean into the wall.  Hold for 10-15 seconds. Repeat with the other arm.'
    },
    abu: {
      text: 'Tilt your head to one side, then to the other side, and then gently tilt it forward and backward.'
    },
    abv: {
      text: 'Reach one arm across your chest, hold onto the elbow with the other hand, and gently pull it in towards your chest. Repeat with the other arm.'
    },
    abw: {
      text: 'Stand up, put one foot on a nearby object, like a chair or step stool, and reach down to touch your toes. Repeat with the other leg.'
    },
    abx: {
      text: 'Stand in a doorway and place one arm on each side of the doorway, then gently lean forward until you feel a stretch in your chest.'
    },
    aby: {
      text: 'Sit on the edge of a chair or on the floor, and place the soles of your feet together, gently pressing down with your elbows to stretch your inner thighs.'
    }
  },
  longBreakIdeas: {
    aaa: {
      title: 'Not alone',
      text: 'Do you find it hard to take a break alone? Try to do it with a co-worker. Aside from making it easier to stick to breaks, you will have a chance to get to know them better. Taking breaks together increases productivity.'
    },
    aab: {
      title: 'Step away',
      text: 'Do you ever notice how your brain can figure things out by itself? All it takes is to step away from the computer and take a break to think about something totally unrelated.'
    },
    aac: {
      title: 'Microbreaks',
      text: 'Rest is a key component in ensuring the performance of the musculoskeletal system. Frequent breaks can decrease the duration of a task and help lower the exposure to ergonomic injury risk.'
    },
    aad: {
      title: 'Meditation',
      text: 'Research studies suggest that mindfulness-based exercises help decrease anxiety, depression, stress, and pain, and help improve general health, mental health, and quality of life. Not sure how to start? There are numerous apps to help you out.'
    },
    aae: {
      title: 'Blink',
      text: 'Looking at screens for a long time causes you to blink less, thus exposing your eyes to the air. Blink rapidly for a few seconds to refresh the tear film and clear dust from the eye surface.'
    },
    aaf: {
      title: 'Ergonomics',
      text: 'Improper height and angle of the keyboard, mouse, monitor or working surface can cause health problems. Take some time to read about desk ergonomics.'
    },
    aag: {
      title: 'Move',
      text: 'There are a lot of ways you can exercise within your office. Try marching in place or doing desk push-ups.'
    },
    aah: {
      title: 'Change',
      text: 'Do you have a stability ball or standing work desk?  It is a sign that you need to take a break.'
    },
    aaj: { title: 'Tech', text: 'How about taking a no-tech walk?' },
    aak: {
      title: 'Metabolism',
      text: 'Emerging research shows that sitting for long periods of time contributes to risk of metabolic syndrome, heart attack and stroke risk and overall death risk, among others. Taking regular walking breaks can help your circulation, working to counteract some of those problems.'
    },
    aal: {
      title: 'Active Meetings',
      text: 'How about moving meetings from the conference room to the concourse? Walking not only burns calories but it may even foster a sense of collaboration.'
    },
    aam: {
      title: 'Fruit',
      text: 'Take your time and eat some fruit. Slowly. Notice the flavor, the texture, the freshness.'
    },
    aan: {
      title: 'Bathrooms',
      text: 'Walk to the farthest bathroom in the worksite facility when going to the restroom.'
    },
    aao: {
      title: 'Coffee break',
      text: 'Going on coffee break? Consider doing a 5-minute walk every time you go for one.'
    },
    aap: {
      title: 'Colleagues',
      text: 'Do not email or message office colleagues, walk to their desks to communicate with them.'
    },
    aaq: {
      title: 'Learning',
      text: 'In a study of healthy volunteers, NIH researchers found that taking short breaks, early and often, may help our brains learn new skills.'
    },
    aar: {
      title: 'Exercise',
      text: 'Evidence suggests small amounts of regular exercise can bring dramatic health benefits, including measurably reducing stress.'
    },
    aas: {
      title: 'Repeat',
      text: 'Have you found your stretch-ly-routine? Do not forget to repeat it for more than once to better fight effects of prolonged sitting.'
    },
    aat: {
      title: 'Wrist and forearm',
      text: 'Extend your arms with the palms facing towards you, then slowly rotate the hands four times clockwise, then four times counter-clockwise.'
    },
    aau: {
      title: 'Back stretching',
      text: 'Join your hands behind your head, then lift them together up above your head ending with your palms facing upward.'
    },
    aav: {
      title: 'Mobilize',
      text: 'For every thirty minutes of stagnation, you should have at least one minute of stimulation.'
    },
    aaw: {
      title: '7 Minute Workout',
      text: 'This workout packs in a full-body exercise routine in a fraction of the time. But as with any exercise, be careful. There are numerous apps to get you started.'
    },
    aax: {
      title: 'Pulse',
      text: 'Raise your pulse rate to 120 beats per minute for 20 straight minutes four or five times a week doing anything you enjoy. Regularly raising your heart rate results in improved cardiovascular health.'
    },
    aay: {
      title: 'Take the stairs',
      text: 'Studies have shown that stair climbing, which is considered vigorous-intensity physical activity, burns more calories per minute than jogging.'
    },
    aaz: {
      title: 'Make art',
      text: 'Art therapy is known to have great mental health benefits, especially when it comes to stress management. How about writing a quick poem, taking a picture or painting something small?'
    },
    aba: {
      title: 'Declutter',
      text: 'A clean space helps your focus at work and is often linked to positive emotions like happiness.'
    },
    abb: {
      title: 'Lunch outside',
      text: 'Nature is linked to positive emotions and decreased stress and anxiety. Whenever possible, try to take your daily lunch break outside, surrounded by some greenery.'
    },
    abc: {
      title: 'Public transport',
      text: 'If you use public transport regularly, you can stand instead of sitting. If it is possible, try to replace as many of your daily trips as possible with walking or cycling.'
    },
    abd: {
      title: 'Yawning',
      text: 'Yawning can be really helpful, as it produces tears to help moisten and lubricate the eyes.'
    },
    abe: {
      title: 'Focus change',
      text: 'Hold one finger close to the eye and focus on it. Slowly move the finger away, focus far into the distance and then back to the finger. Bring the finger back and focus on something far away.'
    },
    abf: {
      title: 'Palming',
      text: 'While seated, brace elbows on the desk and close to the desk edge. Let your weight fall forward and cup hands over eyes. Close your eyes and inhale slowly through nose and hold for few seconds. Continue deep breathing.'
    },
    abg: {
      title: 'Hand squeezes',
      text: 'Squeeze a pair of balled-up socks or a soft rubber ball, hold for 5 seconds. Repeat whole process a few times.'
    },
    abh: {
      title: 'Slow Breathing',
      text: 'Emerging research suggests potential for use of controlled slow breathing techniques as a means of optimising physiological parameters that appear to be associated with health and longevity.'
    },
    abi: {
      title: 'Imaginative visualization',
      text: 'Close your eyes and imagine yourself in a peaceful and calming place, such as a beach or a forest, focusing on the sights, sounds, and sensations of that environment.'
    }
  }
}
19:29:51.750 › Stretchly: loading default break ideas
i18next: languageChanged en
i18next: initialized {
  debug: true,
  initImmediate: true,
  ns: [ 'translation' ],
  defaultNS: [ 'translation' ],
  fallbackLng: [ 'en' ],
  fallbackNS: false,
  supportedLngs: false,
  nonExplicitSupportedLngs: false,
  load: 'all',
  preload: false,
  simplifyPluralSuffix: true,
  keySeparator: '.',
  nsSeparator: ':',
  pluralSeparator: '_',
  contextSeparator: '_',
  partialBundledLanguages: false,
  saveMissing: false,
  updateMissing: false,
  saveMissingTo: 'fallback',
  saveMissingPlurals: true,
  missingKeyHandler: false,
  missingInterpolationHandler: false,
  postProcess: false,
  postProcessPassResolved: false,
  returnNull: false,
  returnEmptyString: true,
  returnObjects: false,
  joinArrays: false,
  returnedObjectHandler: false,
  parseMissingKeyHandler: false,
  appendNamespaceToMissingKey: false,
  appendNamespaceToCIMode: false,
  overloadTranslationOptionHandler: [Function: overloadTranslationOptionHandler],
  interpolation: {
    escapeValue: true,
    format: [Function: bound format],
    prefix: '{{',
    suffix: '}}',
    formatSeparator: ',',
    unescapePrefix: '-',
    nestingPrefix: '$t(',
    nestingSuffix: ')',
    nestingOptionsSeparator: ',',
    maxReplaces: 1000,
    skipOnVariables: true
  },
  lng: 'en',
  backend: {
    loadPath: '/Users/conta/workspace/hovancik/stretchly/app/locales/{{lng}}.json',
    jsonIndent: 2,
    addPath: '/locales/{{lng}}/{{ns}}.missing.json',
    ident: 2,
    parse: [Function: parse],
    stringify: [Function: stringify]
  },
  ignoreJSONStructure: true
}
[1252:1125/192951.917725:WARNING:viz_main_impl.cc(85)] VizNullHypothesis is disabled (not a warning)
19:29:53.117 › Stretchly: checking for new version (local: v1.16.0, remote: 1.16.0)

Not sure what is FocusStatus thingy, I use package macos-notification-state but not sure if that even works. I have not been using mac for years


Vs code compilation experiments

trying to resolve errors thrown in VS Code, packaging for npm
experiments:

following package structure of @angular packages: index.d.ts is slimmed down, code moved to src\interfaces.ts
'Promise' wasn't found as a class, included rxjs-Promises
'String'-usage changed to 'string'
imported interfaces where errors were thrown
'import {default}' threw an error, Classes directly imported

Oh wow, the changes are much more extensive than I had hoped for :)
I will leave you some code comments but I also have two more general questions. Please bear with me, because I'm far from expert on TS/ES6

Do you really find it necessary to have tsconfig.json and actually to do tsc compilation? Personally I only even compiled when bundling.
I'm not convinced about adding rxjs to have Promise. Again, at compilation it seems safe to ignore missing class. At runtime I don't want to enforce any specific implementation there of. I'd rather let the consumer decide to use native (where available) or choose one of the polyfills. And so, maybe simply installing global typings for es6-promise could to the trick?