Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: npm install not working without distutils #1513

Closed
5 tasks done
devtobi opened this issue Nov 21, 2024 · 31 comments · Fixed by #1540
Closed
5 tasks done

[Bug]: npm install not working without distutils #1513

devtobi opened this issue Nov 21, 2024 · 31 comments · Fixed by #1540

Comments

@devtobi
Copy link

devtobi commented Nov 21, 2024

Version

  • I'm using version 1.16

Known issues

  • I've checked Known issues

Existing issues

  • I've checked Existing issues

Advanced Preferences

  • I've checked Advanced Preferences

What operating system are you using?

macOS

Operating System Version

macOS 15.1.1

Reproduction steps

  1. I installed suggested node version 20.18.0
  2. Checked out the source code
  3. 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

  • I agree to follow this project's Code of Conduct
@devtobi
Copy link
Author

devtobi commented Nov 21, 2024

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.

@devtobi
Copy link
Author

devtobi commented Nov 21, 2024

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?

@hovancik
Copy link
Owner

hovancik commented Nov 22, 2024

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.

@devtobi
Copy link
Author

devtobi commented Nov 23, 2024

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://127.0.0.1:9222/devtools/browser/88cdfd94-11f9-446c-82cd-46b737e920f8
12:33:47.990Stretchly: initializing...
12:33:47.997Stretchly: loading preferences
12:33:48.001Stretchly: starting Idle time monitoring
12:33:48.005Stretchly: 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.114Stretchly: 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."
    },
    abh: {
      text: 'Make a fist and then fan your fingers out and stretch them as far as you can.'
    },
    abi: {
      text: 'Sit tall, arms hanging at your sides, and slowly rotate neck in one direction in a large circle.'
    },
    abj: {
      text: 'Stand tall and slowly tilt your head toward the shoulder using the same hand until you feel a stretch.'
    },
    abk: {
      text: 'Stand tall with your arms by your side. 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. Repeatwith the other foot.'
    },
    abo: {
      text: 'Stand with your feet shoulder-width apart, lower your body down as if you were sitting back into a chair, then stand back up. Repeat several times.'
    },
    abp: {
      text: 'Stand with your back and hands on a wall, then slowly move your arms up and down as if you were making snow angels.'
    },
    abq: {
      text: 'Stand facing a wall and place your hands on it, then do several push-ups.'
    },
    abr: {
      text: 'Sit on the edge of your chair and extend one leg straight out in front of you, holding 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. Repeat with the other leg.'
    },
    abt: {
      text: 'Hold one arm straight up, then use the other arm to gently push the elbow of the first arm towards your head. 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? Consider replacing your desk chair with them for a while.'
    },
    aai: {
      title: 'Notice',
      text: 'Are you daydreaming or having trouble focusing? 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.228Stretchly: 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

@devtobi
Copy link
Author

devtobi commented Nov 23, 2024

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.

@devtobi
Copy link
Author

devtobi commented Nov 23, 2024

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

@hovancik
Copy link
Owner

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

@devtobi
Copy link
Author

devtobi commented Nov 23, 2024

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

@hovancik
Copy link
Owner

Uf, at loss here. Maybe try running example electron app if that works?

https://github.com/electron/electron-quick-start

@devtobi
Copy link
Author

devtobi commented Nov 24, 2024

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 ferdium/ferdium-app#1892 (comment) 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.

@hovancik
Copy link
Owner

This is my output:

➜  stretchly git:(trunk) npm run dev

> [email protected] dev
> cross-env NODE_ENV=development electron . --trace-warnings --trace-deprecation --enable-logging --remote-debugging-port=9222


DevTools listening on ws://127.0.0.1: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."
    },
    abh: {
      text: 'Make a fist and then fan your fingers out and stretch them as far as you can.'
    },
    abi: {
      text: 'Sit tall, arms hanging at your sides, and slowly rotate neck in one direction in a large circle.'
    },
    abj: {
      text: 'Stand tall and slowly tilt your head toward the shoulder using the same hand until you feel a stretch.'
    },
    abk: {
      text: 'Stand tall with your arms by your side. 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 foot.'
    },
    abo: {
      text: 'Stand with your feet shoulder-width apart, lower your body down as if you were sitting back into a chair, then stand back up. Repeat several times.'
    },
    abp: {
      text: 'Stand with your back and hands on a wall, then slowly move your arms up and down as if you were making snow angels.'
    },
    abq: {
      text: 'Stand facing a wall and place your hands on it, then do several push-ups.'
    },
    abr: {
      text: 'Sit on the edge of your chair and extend one leg straight out in front of you, holding 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. Repeat with the other leg.'
    },
    abt: {
      text: 'Hold one arm straight up, then use the other arm to gently push the elbow of the first arm towards your head. 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? Consider replacing your desk chair with them for a while.'
    },
    aai: {
      title: 'Notice',
      text: 'Are you daydreaming or having trouble focusing? 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)

@hovancik
Copy link
Owner

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

@hovancik
Copy link
Owner

hovancik commented Jan 2, 2025

@devtobi were you able to move forward?

@devtobi
Copy link
Author

devtobi commented Jan 2, 2025

I just tried it with the latest version of Stretchly (1.17.1). However I still got the same behaviour as mentioned earlier.

  • npm run lint and npm run test works fine
  • npm run pack produces a runnable application
  • npm run start and npm run dev lead to a crash with stretchly/node_modules/electron/dist/Electron.app/Contents/MacOS/Electron exited with signal SIGABRT

Actually I don't know how to look further into this for now. As mentioned above debugging the error is somehow not possible. I can't investigate where the SIGABRT signal is coming from.. This would help tremendously of course.
If you still have an idea let me know. I think what also would help is maybe another person also using an Apple silicon machine with the latest OS version?

I want to contribute to the development of Stretchly in 2025, so that's why I opened up the issue initially.
I can develop using npm run pack (which is of course kind of uncomfortable) but still somehow doable.
So I leave it to you if you wan't to further investigate or close the issue.

@hovancik
Copy link
Owner

hovancik commented Jan 2, 2025

I would try removing stretchly and clone git again. Before npm i I would remove all node/npm/electron caches.
There might be more but internet suggests npm cache clean --force

rm -rf ~/Library/Caches/electron-*

Never had issues with MacOS (but not using it anymore), but Windows is usually painful, and it helps me often to remove all possible caches and so on

@devtobi
Copy link
Author

devtobi commented Jan 2, 2025

Thanks for your suggestions. But unfortunately that did not help either. Still the same error message.
It must be something specific to electron, which you make use of in your app.
As mentioned the electron example app works like a charm on my machine.

I even just completely resetted my python setup as I previously used python via homebrew. I switched to a dedicated python version manager but still same issue. So it really seems to be a really specific electron-based problem.

When running npm install I get a lot of deprecation warnings about packages being pulled. Might this be an issue regarding the development dependencies (especially on newer machines?)

Output of npm install:
CleanShot 2025-01-02 at 15 19 33

@hovancik
Copy link
Owner

hovancik commented Jan 2, 2025

I am seeing deprecations on Linux as well.

Maybe you could get crash info from mac OS as other user here? #1529 (comment)

@devtobi
Copy link
Author

devtobi commented Jan 2, 2025

Indeed the crash info helped out and confirmed the assumption I posted earlier in #1513 (comment)

The important part is:

Exception Type:        EXC_CRASH (SIGABRT)
Termination Reason:  
This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSFocusStatusUsageDescription key with a string value explaining to the user how the app uses this data.

Since you added NSFocusStatusUsageDescription inside the package.json file it looks like this is only respected when building the .app and not when running via npm run start or npm run dev.

@hovancik
Copy link
Owner

hovancik commented Jan 2, 2025

Yeah that is electron-builder config.

Maybe try disabling checking for DND? In preferences file there is monitorDnd. It will not call dnd check and thus maybe no crash.

Did you get macOS prompt to allow Stretchly to access DND? Not sure if that would change anything as nom run dev is Electron rather then Stretchly.

@devtobi
Copy link
Author

devtobi commented Jan 2, 2025

I only got the macOS prompt for the packaged version of the app (so Stretchly directly), but not when running via "npm run start" or "npm run dev" (Electron). Should this normally be the case?
I also already checked macOS privacy settings but did not find a way to enable DND access for Electron.

Disabling the feature completely (for development purposes) is a pretty hacky workaround in my opinion.

@hovancik
Copy link
Owner

hovancik commented Jan 2, 2025

I also am not getting Focus prompt in Electron.

DND does not work currently in MacOS anyway

@devtobi
Copy link
Author

devtobi commented Jan 2, 2025

So that means you did not allow focus access on your side but still the app does not crash? Might this be because you disabled DND access in the preferences? (So basically what you suggested above).
If DND does not work anyways, why not remove it from Stretchly for the macOS build, so that the app does not ask for access permission?

@hovancik
Copy link
Owner

hovancik commented Jan 3, 2025

So my DND is enabled and with iTerm I was not getting any errors, all was working fine, no Focus prompt.

Today I made a small change, added log

else if (process.platform === 'darwin') {
        console.log(this.macosNotificationState);
        return this.macosNotificationState.getDoNotDisturb()

and then with iTerm it crashed.

So I went to try with default Terminal app and I got focus prompt (with changed code with log):

Screenshot 2025-01-03 at 8 14 55

I was not removing it because I would like to fix it (it worked in previous macOS versions), but as I don't have supported mac, it's not easy.

Now that with latest macOS we are getting Focus prompt, maybe we should be able to fix, might be something wrong with my code.

@hovancik
Copy link
Owner

hovancik commented Jan 3, 2025

Seems like we check DND with defaults read com.apple.controlcenter "NSStatusItem Visible FocusModes"

@devtobi
Copy link
Author

devtobi commented Jan 7, 2025

As you stated above I tried running the npm job with the normal terminal app and suddenly I get the focus prompt and the app starts as usual.
So the problem the whole time was me using the "wrong" terminal. However I wonder why the popup only appears on the native terminal app and not others? (I am using ghostty by the way and used kitty before, both not working).

@hovancik
Copy link
Owner

hovancik commented Jan 8, 2025

Probably Apple being Apple :)

I've removed that functionality and started using command line query. Does that work for you? I've built some test installers https://conta.noho.st/nextcloud/s/Q6X3Z694maFysrc

@devtobi
Copy link
Author

devtobi commented Jan 11, 2025

Probably Apple being Apple :)

I've removed that functionality and started using command line query. Does that work for you? I've built some test installers https://conta.noho.st/nextcloud/s/Q6X3Z694maFysrc

Thanks for providing those installers. After installing the app I did not get the popup to allow focus access. So I am not 100% if that works. However that might also be because I denied access in the past. I checked privacy settings of macOS and found a new "Stretchly" entry there, so it looks like it somehow detected the app wants DnD access.

However when running the app and "DnD" enabled in macOS the app does not respect the setting and always show the break popup, so the functionality seems to be broken.
I ran defaults read com.apple.controlcenter "NSStatusItem Visible FocusModes" manually and it always returned 0.
I also researched a bit and it looks like we only have write access to DND mode (via shortcuts) but no reading.

To end with a positive thing: I checked out your fix/dnd-mac branch and I am happy to tell you that the app no longer crashes when running via npm run start or npm run dev. I tried this in multiple terminals 😄
However this might be coupled to the problem that "DnD" functionality is broken, so we will see..

@hovancik
Copy link
Owner

In new DND implementation I don't ask for permissions as I use different way to check for it, so that's why it's not asking for permission anymore.

Do you use default DND or some custom Focus mode?

For me DND works

image

@devtobi
Copy link
Author

devtobi commented Jan 11, 2025

I am using the default DND mode. So does the defaults command you used for implementing toggle between 0 and 1 for you when you switch DND mode on/off.
This does not happen on my machine and thus I don't get to see the pausing of Stretchly. :(

@devtobi
Copy link
Author

devtobi commented Jan 17, 2025

@hovancik if it makes more sense we can move further discussion about DND into a separate issue and you can merge the fix for now?

@hovancik
Copy link
Owner

Hi, yes. I plan to merge the new way, release new minor version and we will see how it behaves in wild.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants