Compare commits

..
1223 Commits
Author SHA1 Message Date
Vlad Hashimoto 0bc8389c6c chore: ensure yarn is installed before launching fiddle (#452) 2020-10-09 23:30:20 +03:00
Mitchell Woodhouse Mckenzie 2cb8e23bc2 fix: theme select popover closing settings when pressing escape (#498) 2020-10-09 13:09:59 -07:00
Shelley Vohr 8afff13f8d feat: allow setting gist description (#492) 2020-10-08 11:20:36 -07:00
dependabot[bot] 0abc4fb9a9 build(deps-dev): bump electron from 9.3.0 to 9.3.1 (#500)
Bumps [electron](https://github.com/electron/electron) from 9.3.0 to 9.3.1.
- [Release notes](https://github.com/electron/electron/releases)
- [Changelog](https://github.com/electron/electron/blob/master/docs/breaking-changes.md)
- [Commits](https://github.com/electron/electron/compare/v9.3.0...v9.3.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-10-06 23:11:35 +03:00
dependabot[bot] 5f2563b39f build(deps-dev): bump electron from 9.1.1 to 9.3.0 (#499)
Bumps [electron](https://github.com/electron/electron) from 9.1.1 to 9.3.0.
- [Release notes](https://github.com/electron/electron/releases)
- [Changelog](https://github.com/electron/electron/blob/master/docs/breaking-changes.md)
- [Commits](https://github.com/electron/electron/compare/v9.1.1...v9.3.0)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-10-06 08:28:56 -07:00
github-actions[bot]andmalept 889528c4d1 build: update Electron releases JSON (#497)
Co-authored-by: malept <electron-bot@users.noreply.github.com>
2020-10-05 08:02:43 -07:00
Erick Zhao 7cd6908009 docs: add Discord Server to README (#496) 2020-10-02 15:24:09 -07:00
Charles KerrandMark Lee e3e148d1e8 refactor: prefer app.whenReady() over .on('ready') (#362)
Co-authored-by: Mark Lee <malept@users.noreply.github.com>
2020-09-30 16:01:22 -07:00
Erick Zhao 1448bc6d55 chore: update-electron-app 2 (#494) 2020-09-29 09:31:50 -07:00
github-actions[bot]andmalept ea92d8130f build: update Electron releases JSON (#493)
Co-authored-by: malept <electron-bot@users.noreply.github.com>
2020-09-28 10:21:32 -07:00
Shelley Vohr 6e54dd6493 refactor: clean up gist action states (#491)
* refactor: clean up gist action states

* fix: tweak small state edge case
2020-09-24 16:40:14 -07:00
dependabot[bot] 24435b3f1a build(deps-dev): bump node-fetch from 2.6.0 to 2.6.1 (#475)
Bumps [node-fetch](https://github.com/bitinn/node-fetch) from 2.6.0 to 2.6.1.
- [Release notes](https://github.com/bitinn/node-fetch/releases)
- [Changelog](https://github.com/node-fetch/node-fetch/blob/master/docs/CHANGELOG.md)
- [Commits](https://github.com/bitinn/node-fetch/compare/v2.6.0...v2.6.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-09-23 18:01:26 -07:00
github-actions[bot]andmalept 973cf1bd2d build: update Electron releases JSON (#490)
Co-authored-by: malept <electron-bot@users.noreply.github.com>
2020-09-21 17:00:34 +03:00
Shelley Vohr 2a0160f4f9 fix: version prerelease sorting (#485) 2020-09-19 20:59:04 -06:00
Shelley Vohr fccc7831db fix: gist action state management (#488) 2020-09-18 17:13:50 -06:00
Jeremy Rose a1ec0bf259 feat: show a link to the comparison range on bisect complete (#481) 2020-09-18 23:32:36 +03:00
Shelley Vohr 54c02ac35d fix: selectAll should work in text fields (#483) 2020-09-18 12:50:42 -06:00
Shelley Vohr ac05d578ce feat: add unique icons for gist actions (#489) 2020-09-18 12:18:19 -06:00
Shelley Vohr f1cf7db354 feat: add ability to delete gists (#484) 2020-09-17 17:41:51 -06:00
malept 6e40af3bf4 build: update Electron releases JSON 2020-09-14 23:40:41 -07:00
github-actions[bot]andmalept 424d87b63d build: update Electron releases JSON (#473)
Co-authored-by: malept <electron-bot@users.noreply.github.com>
2020-08-31 09:39:49 -07:00
Erick Zhao 33c0832e83 chore: only enable Sentry in production (#472) 2020-08-27 13:30:30 -07:00
github-actions[bot]andElectron Bot 1a0e21d9fa build: update Electron releases JSON (#466)
Co-authored-by: Electron Bot <electron-bot@users.noreply.github.com>
2020-08-24 13:40:42 -07:00
Shelley Vohr 5044ca7f31 fix: move updating state out of try/catch (#465) 2020-08-23 17:25:13 -07:00
Vlad Hashimoto 23900196e7 feat: release v0.16.0 (#463) 2020-08-22 01:12:14 +03:00
Shelley Vohr 604f3190b7 fix: handle Fiddle update failure (#464) 2020-08-21 14:44:22 -07:00
github-actions[bot]andmalept fc3ed6f4f6 build: update Electron releases JSON (#460)
Co-authored-by: malept <electron-bot@users.noreply.github.com>
2020-08-17 20:18:12 +03:00
github-actions[bot]andmalept c5d0e3b156 build: update Electron releases JSON (#457)
Co-authored-by: malept <electron-bot@users.noreply.github.com>
2020-08-10 23:08:13 +03:00
Vlad Hashimoto 7705fdc80c build: update electron-devtools-installer to latest version (#455) 2020-08-10 23:07:06 +03:00
Erick Zhao a436b021b0 chore: proper TypeScript in renderer/state.ts (#453) 2020-08-06 09:57:34 -07:00
Vlad Hashimoto f9fe9dba84 feat: add ability to select package between npm and yarn (#447) 2020-08-06 08:45:34 +03:00
Erick Zhao 7bab157863 build: replace TSLint with ESLint and Prettier (#445) 2020-08-05 14:14:33 -07:00
dependabot[bot] ac6c7cde1c build(deps): bump elliptic from 6.5.2 to 6.5.3 (#450)
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.2 to 6.5.3.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.2...v6.5.3)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-08-04 09:25:00 -07:00
github-actions[bot]andElectron Bot 1dc64f4c53 build: update Electron releases JSON (#451)
Co-authored-by: Electron Bot <electron-bot@users.noreply.github.com>
2020-08-02 19:06:48 -07:00
github-actions[bot]andmalept 836a80c6f1 build: update Electron releases JSON (#448)
Co-authored-by: malept <electron-bot@users.noreply.github.com>
2020-07-27 13:21:18 -07:00
Erick Zhao 4825900ae0 build: upgrade to Electron 9 (#446) 2020-07-27 11:21:48 -07:00
Aniruddha Shastri 6f2218e239 fix: transparent BrowserWindow show-me on Windows (#424)
* fix: transparent BrowserWindow show-me on win32

The `transparent` configuration on Windows OS requires the window to also be frameless. Updating the show-me to handle this.

Documented at the entry for `transparent` at the [BrowserWindow API doc](https://www.electronjs.org/docs/api/browser-window#new-browserwindowoptions)

* Address suggestions

* Update comment to say 'platforms' instead of 'OS'
2020-07-22 14:55:06 -07:00
dependabot[bot]andErick Zhao ca1c49a238 build(deps-dev): bump electron from 8.0.2 to 8.2.4 (#432)
* build(deps-dev): bump electron from 8.0.2 to 8.2.4

Bumps [electron](https://github.com/electron/electron) from 8.0.2 to 8.2.4.
- [Release notes](https://github.com/electron/electron/releases)
- [Changelog](https://github.com/electron/electron/blob/master/docs/breaking-changes.md)
- [Commits](https://github.com/electron/electron/compare/v8.0.2...v8.2.4)

Signed-off-by: dependabot[bot] <support@github.com>

* test: update possibly null type in spec

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Erick Zhao <ezhao@slack-corp.com>
2020-07-22 14:54:05 -07:00
Erick Zhao d346a91af9 build(deps): upgrade electron-default-menu to 1.0.2 (#444) 2020-07-21 17:33:40 -07:00
github-actions[bot]andmalept e675f8f482 build: update Electron releases JSON (#443)
Co-authored-by: malept <electron-bot@users.noreply.github.com>
2020-07-21 10:40:25 -07:00
Vlad Hashimoto eb03608473 chore: update forge in the packaged app (#442) 2020-07-21 02:59:42 +03:00
Erick Zhao d3b10ee773 refactor: move about-panel function (#428) 2020-07-16 14:50:02 -07:00
Erick Zhao 2a75120dd9 chore: remove unused code from TouchBar manager (#429) 2020-07-16 14:49:47 -07:00
Erick Zhao 7177bce5f8 fix: add functioning Select All menu item (#438) 2020-07-16 14:25:36 -07:00
Erick Zhao bfb54690b9 fix: proper toggling for devtools (#439) 2020-07-16 14:25:00 -07:00
dependabot[bot] b5a572bbae build(deps): bump lodash from 4.17.15 to 4.17.19 (#440)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-07-16 15:50:22 +03:00
Erick ZhaoandVlad Hashimoto cd2e719994 fix: clearer document titles (#437)
Co-authored-by: Vlad Hashimoto <hashimoto.stream@gmail.com>
2020-07-15 13:28:11 -07:00
github-actions[bot]andElectron Bot b5ab9c1a75 build: update Electron releases JSON (#436)
Co-authored-by: Electron Bot <electron-bot@users.noreply.github.com>
2020-07-13 12:24:42 -07:00
Mark Lee 0c4a09cca6 build(deps-dev): upgrade electron-forge to ^6.0.0-beta.52 (#435)
* build(deps-dev): upgrade node-abi to ^2.18.0
2020-07-08 18:17:03 -07:00
Erick Zhao 2a67e7e6cf fix: consistent app quit dialog behaviour (#423) 2020-07-07 12:21:15 -07:00
Vlad Hashimoto 351c5caf23 feat: set the appData dir from the main process (#430) 2020-07-06 23:31:34 +03:00
github-actions[bot]andmalept 36780a95e7 build: update Electron releases JSON (#431)
Co-authored-by: malept <electron-bot@users.noreply.github.com>
2020-07-06 03:59:28 +03:00
Shelley Vohr 9065a8678a fix: audio/video entitlements crash (#426)
* fix: add entitlements for audio and video capture

* chore: add usageDescription

* empty commit
2020-07-01 12:49:39 -07:00
github-actions[bot]andmalept 016d3ee78a build: update Electron releases JSON (#419)
Co-authored-by: malept <electron-bot@users.noreply.github.com>
2020-06-29 20:02:40 +03:00
Shelley Vohr 4b40420bba feat: log notification info in adv logging (#421) 2020-06-25 11:30:28 -07:00
Vlad Hashimoto 0e872b0dd0 feat: allow to publish if user would to do it (#413) 2020-06-18 15:11:06 +03:00
github-actions[bot]andmalept 7638111598 build: update Electron releases JSON (#414)
Co-authored-by: malept <electron-bot@users.noreply.github.com>
2020-06-16 08:14:39 -07:00
Benjamin Sova a0e59ad288 docs: fix explanation of darwin auto-quit prevention (#410) 2020-06-11 09:48:38 -07:00
Erick Zhao 3c6103dc50 chore: 0.15.1 (#409) 2020-06-09 10:24:32 -07:00
Erick Zhao b98472f973 fix: make hidden editors interact properly with remote content (#404) 2020-06-08 16:37:20 -07:00
Jeremy Rose 3602eacc88 fix: correct sense of bisect buttons (#408) 2020-06-08 16:19:54 -07:00
github-actions[bot] 8b84c040c7 build: update Electron releases JSON (#399) 2020-06-07 20:36:37 -07:00
Erick Zhao 6aa19eada6 fix: proper async/await usage in editor.tsx (#403) 2020-06-01 14:39:41 -07:00
Erick Zhao 8e92183de2 refactor: replace app.getName() with app.name (#401) 2020-05-27 16:03:17 -07:00
Vlad Hashimoto 1a951f3f44 feat: v0.15.0 (#398) 2020-05-23 02:46:28 +03:00
Will Anderson 66ead93f05 fix: Update documentation link for user-provided flags (#397) 2020-05-23 00:26:09 +03:00
Vlad Hashimoto d22899b4a5 feat: add ability to update gist instead of publishing (#386) 2020-05-22 23:59:27 +03:00
Vlad Hashimoto 77d4bc6fc5 fix: use role: quit for render exit button in menu (#395) 2020-05-21 00:45:41 +03:00
github-actions[bot] 961d42d74f build: update Electron releases JSON (#393) 2020-05-20 21:33:13 +03:00
Vlad Hashimoto c58ade2132 fix: reset github token when authentication failed (#388) 2020-05-20 21:31:00 +03:00
github-actions[bot] 592c220f18 build: update Electron releases JSON (#391) 2020-05-13 21:13:51 +03:00
Vlad Hashimoto 4da0e82e9b fix: set the window to null after destroying (#389) 2020-05-13 20:54:18 +03:00
Vlad Hashimoto f766bef10c fix: doesn't error when unable to watch file (#390) 2020-05-12 19:36:28 -07:00
Natalie 30ba9fb023 docs: improve CONTRIBUTING.md (#380)
This PR adds a Contributing section to the README and descriptive text for running Fiddle from source in CONTRIBUTING.md.
2020-05-12 08:53:17 -07:00
github-actions[bot] f3e847da85 build: update Electron releases JSON (#381) 2020-05-04 23:42:14 -07:00
Kimberlee Johnson 0f854441e4 feat: reset layout button (#374) 2020-04-29 17:35:18 -07:00
Vlad Hashimoto f31a4e38bb fix: don't modify state directly (#385) 2020-04-28 14:18:18 -07:00
Felix Rieseberg 26bb3e4944 Merge pull request #373 from codebytere/update-electron-get
chore: update @electron/get version
2020-04-21 11:03:20 -07:00
Vlad Hashimoto fb1fb7869c Merge pull request #376 from electron/update-releases
build: update Electron releases JSON
2020-04-20 12:21:15 +03:00
malept a1e67400bf build: update Electron releases JSON 2020-04-20 00:04:55 +00:00
Shelley Vohr a26aa1e70c chore: update @electron/get version 2020-04-14 14:22:25 -07:00
github-actions[bot]andElectron Bot 78395412f4 build: update Electron releases JSON (#368)
Co-authored-by: Electron Bot <electron-bot@users.noreply.github.com>
2020-04-13 07:51:52 -07:00
Felix Rieseberg 1f72db3cfc 0.14.0 2020-04-06 10:22:19 -07:00
Felix Rieseberg c333a1e132 Merge pull request #366 from electron/update-releases
build: update Electron releases JSON
2020-04-06 10:19:49 -07:00
malept a0a989d7a7 build: update Electron releases JSON 2020-04-06 00:13:17 +00:00
github-actions[bot]andmalept 5b07b8a706 build: update Electron releases JSON (#364)
Co-authored-by: malept <electron-bot@users.noreply.github.com>
2020-03-30 03:20:17 +03:00
Felix Rieseberg 98a358b756 Merge pull request #358 from electron/download-progress
Refactor BinaryManager, add download progress indicator
2020-03-24 11:14:55 -07:00
Felix Rieseberg 9b55b2ef26 Merge pull request #357 from electron/no-notarize
build: Only notarize during make
2020-03-23 10:45:16 -07:00
Felix Rieseberg 5b91177348 Merge pull request #359 from electron/update-releases
build: update Electron releases JSON
2020-03-23 10:44:51 -07:00
malept f8c43a07f7 build: update Electron releases JSON 2020-03-23 00:04:50 +00:00
Felix Rieseberg 5eba9cdbe2 feat: A fancy spinner for downloading 2020-03-17 18:11:05 -07:00
Felix Rieseberg 8ee42c290e test: Fix the tests post-refactor 2020-03-17 17:58:25 -07:00
Felix Rieseberg c2b3954dfa chore: Refactor BinaryManager, no more classes 2020-03-17 17:07:25 -07:00
Felix Rieseberg e61599e9c5 chore: Better named interfaces 2020-03-17 16:24:58 -07:00
Felix RiesebergandMark Lee 1fed772a27 Update forge.config.js
Co-Authored-By: Mark Lee <malept@users.noreply.github.com>
2020-03-17 16:13:32 -07:00
Felix RiesebergandMark Lee de85d0f324 Update forge.config.js
Co-Authored-By: Mark Lee <malept@users.noreply.github.com>
2020-03-17 16:13:16 -07:00
Erick Zhao c89671d99d feat: improved bisect commands UX (#352) 2020-03-16 10:55:34 -07:00
Felix Rieseberg 155b901ade build: Only notarize during make 2020-03-16 10:47:00 -07:00
github-actions[bot]andmalept 8e098deab8 build: update Electron releases JSON (#356)
Co-authored-by: malept <electron-bot@users.noreply.github.com>
2020-03-16 02:18:36 +02:00
dependabot[bot] 2b5ea7d467 build(deps): bump acorn from 5.7.1 to 5.7.4
Bumps [acorn](https://github.com/acornjs/acorn) from 5.7.1 to 5.7.4.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/5.7.1...5.7.4)

Signed-off-by: dependabot[bot] <support@github.com>
2020-03-13 23:49:10 -07:00
Vlad Hashimoto 91efa5a009 v0.13.1 2020-03-13 16:45:08 -07:00
Erick Zhao 4ec5bec719 fix: load unsave handlers only after editors mount (#351) 2020-03-12 11:53:29 -07:00
Erick Zhao 84ac41f147 feat: more sensible version filtering (#344) 2020-03-12 11:46:32 -07:00
Erick Zhao e9a2985291 fix: preserve 'downloading' version state post-refresh (#345) 2020-03-12 11:46:24 -07:00
Erick ZhaoandFelix Rieseberg 9b28919203 feat: show inactive window on quit warning (#348)
Co-authored-by: Felix Rieseberg <felix@felixrieseberg.com>
2020-03-12 11:13:08 -07:00
Erick Zhao 8d43836787 fix: ensure you have at least one editor open (#347) 2020-03-11 12:54:16 -07:00
Shelley Vohr 48d0dadf5d chore: fix test:report bailing (#349) 2020-03-11 12:32:03 -07:00
Erick Zhao 2f9ef21251 fix: ensure hidden panels work on first load (#346) 2020-03-11 12:12:09 -07:00
Erick Zhao 8e4238275c refactor: grab release list from unpkg (#339) 2020-03-09 11:45:54 -07:00
Shelley Vohr 32d5ea99aa chore: add test report generation helper (#340) 2020-03-09 09:28:43 -07:00
Felix Rieseberg da2e17cd37 Merge pull request #342 from electron/update-releases
build: update Electron releases JSON
2020-03-08 18:13:01 -07:00
malept 539f5bce97 build: update Electron releases JSON 2020-03-09 00:06:03 +00:00
Mark Lee 228552c8a0 build: create a PR for releases.json updates instead of trying to push to master (#341)
* Move expected version count & latest Electron version to its own
  fixture file
* Automatically update expected version count & latest Electron version
  when updating the JSON file
* Throw an error if a rejection occurs when the fetch releases script
  is run
* reduce releases update frequency to once a week
2020-03-06 16:17:42 -08:00
Felix Rieseberg ed8d76a54a fix: Sentry is a runtime dependency 2020-03-02 17:14:29 -08:00
Felix Rieseberg 2f4d47a0ab 0.13.0 2020-03-02 16:14:25 -08:00
Mark Lee 9b443de137 build: auto-update the Electron Releases JSON file every day (#331) 2020-03-02 16:08:39 -08:00
Felix Rieseberg efb5bf0e57 Merge pull request #334 from electron/travis-cleanup
build: cache/install node deps per Travis docs, remove deprecated option
2020-03-02 16:03:59 -08:00
Mark Lee c420747bb9 build: cache/install node dependencies per Travis docs, remove deprecated option 2020-03-02 15:40:23 -08:00
Felix Rieseberg 33223e7b37 Merge pull request #333 from electron/use-bionic
build: Use Ubuntu 18.04 in Travis CI
2020-03-02 15:35:04 -08:00
Felix Rieseberg 86cc0c62a1 build: Use Bionic 2020-03-02 14:50:40 -08:00
Felix Rieseberg 96bd2e36dd Merge pull request #330 from electron/update-dependencies
Update dependencies
2020-03-02 13:02:16 -08:00
Felix Rieseberg 9db527773b test: Fix the tests 2020-02-27 17:43:16 -08:00
Felix Rieseberg 9da1acafd9 wip 2020-02-27 16:56:51 -08:00
Felix Rieseberg 5a05d34776 chore: Update local Electron releases 2020-02-27 14:42:39 -08:00
Felix Rieseberg 6b9d2b66e2 wrench: Update dependencies 2020-02-27 14:41:44 -08:00
Felix Rieseberg d4096a6de8 Merge pull request #329 from electron/less-listeners
chore: Unregister various listeners
2020-02-26 12:28:55 -08:00
Erick Zhao 3709d122a6 feat: add CSS support (#327) 2020-02-22 11:48:11 -08:00
Felix Rieseberg 0368cda57a Merge pull request #328 from electron/fix/remove-reload
fix: remove broken "Reload" menu item
2020-02-22 08:53:34 -08:00
Felix Rieseberg 433cb6acd5 chore: Use node environment where available 2020-02-22 08:50:56 -08:00
Felix Rieseberg 56dceaefb0 chore: Don't collect coverage locally 2020-02-22 08:35:35 -08:00
Erick Zhao 80da23c4e4 fix: remove broken "Reload" menu item 2020-02-21 10:09:41 -08:00
Felix Rieseberg 353968ef8e Merge pull request #326 from electron/bisect-constraint
feat: Add some help to the bisect
2020-02-19 13:29:05 -08:00
Felix RiesebergandErick Zhao 64ece1b364 Apply suggestions from code review
Co-Authored-By: Erick Zhao <erick@hotmail.ca>
2020-02-19 12:29:20 -08:00
Felix Rieseberg 13383f7345 chore: Unregister various listeners 2020-02-15 20:50:57 -08:00
Felix Rieseberg cae7222636 feat: Add some help to the bisect 2020-02-15 20:11:08 -08:00
Felix Rieseberg 2aabe80f2b Merge pull request #324 from electron/fix-bisect
fix: Reorganize the bisect helper
2020-02-15 18:54:11 -08:00
Erick Zhao d0683f1392 fix: prevent other editors from clipping tooltips (#294) 2020-02-13 11:45:42 -08:00
Felix Rieseberg 389352cefa test: Get some of that coverage back 2020-02-12 20:50:18 -08:00
Felix Rieseberg d04b654c3e fix: Reorganize the bisect helper 2020-02-12 14:24:57 -08:00
Felix Rieseberg 1369c9b35c Merge pull request #318 from electron/sentry
chore: add sentry for crash / js error reporting
2020-02-11 07:56:12 -08:00
Samuel Attard 9957090d25 Update electron.ts 2020-02-05 15:14:25 -08:00
Samuel Attard 8a002fb0a8 chore: add sentry for crash / js error reporting 2020-02-05 13:15:02 -08:00
Mark Lee cae8dde4c8 refactor(show-me): avoid using a global mainWindow variable (#314) 2020-02-03 14:19:04 -08:00
Jeremy Apthorp cb176534f9 fix: stop holding a reference to mainWindow (#312) 2020-01-30 09:37:34 -08:00
Erick Zhao f7fa9a8ffc chore: merge pull request #306 from issacgerges/bisect-success-dialog
feat: bisect success dialog
2020-01-29 09:54:24 -08:00
Issac Gerges 347384a547 chore: improve GenericDialog test coverage 2020-01-28 19:22:58 -08:00
Issac Gerges e272efb3b9 fix: add quoted escapes to paths to prevent param expansion on zsh. Remove dead code. 2020-01-28 19:16:22 -08:00
Mark LeeandFelix Rieseberg 5255bcb842 chore: add contributing guide (#311)
Co-Authored-By: Felix Rieseberg <felix@felixrieseberg.com>
2020-01-28 18:51:54 -08:00
Felix Rieseberg d3cd53f3e0 Merge pull request #309 from electron/erick/pong-prints-pong
fix: print correct output in ipcRenderer show-me
2020-01-28 17:45:51 -08:00
Erick Zhao 6d28c4c81b fix: print correct output in ipcRender show-me 2020-01-28 14:55:56 -08:00
Issac Gerges a45354e1af chore: quote lint glob to prevent zsh to parse it as parameter expansion 2020-01-27 18:25:50 -08:00
Issac Gerges 28245d36ba refactor: rename DialogType 'message' to 'success' 2020-01-27 14:48:30 -08:00
Issac Gerges 582ef280b5 Merge remote-tracking branch 'upstream/master' into bisect-dialog 2020-01-27 13:00:48 -08:00
Issac Gerges 56b7f2ffb7 refactor: replace warning/confirmation dialogs with generic dialog and type parameter 2020-01-27 12:58:11 -08:00
issacgerges cb3ba4f0a7 chore: Add issacgerges as a contributor (#304) 2020-01-26 13:57:32 -08:00
Felix Rieseberg e238b10f1e Merge pull request #303 from issacgerges/fix-remote-warning
fix: Make example warning more descriptive
2020-01-26 08:59:37 -08:00
Felix Rieseberg bbc22d9ca8 Merge pull request #301 from issacgerges/support-original-fs
fix: Add original-fs to ignored modules
2020-01-26 08:58:34 -08:00
issacgerges 7b3c960c1f chore: fix autoUpdater example to remove spurious event (#302)
Fixes #283
2020-01-25 22:44:06 -08:00
Issac Gerges 4dbc74fccb fix: Make example warning more descriptive by adding path, remove repeated text. Fixes #262. 2020-01-25 22:02:57 -08:00
Issac Gerges f71b1bc8d4 fix: Add original-fs to ignored modules. Fixes #231 2020-01-25 11:36:25 -08:00
Issac Gerges 00c2e1f9a6 style: fixup jsdoc for BisectDialog 2020-01-25 10:28:43 -08:00
Issac Gerges 50f69613dd feat: Add bisect complete dialog. Fixes #299. 2020-01-25 10:28:35 -08:00
Felix Rieseberg 4a23b53b1b 0.12.0 2020-01-15 12:38:05 -08:00
Felix Rieseberg dcd21935a9 Merge pull request #293 from electron/fix-loading-preload
fix: Create initial backup for preload editor
2020-01-15 12:36:43 -08:00
Felix Rieseberg ff37d5cfb9 test: Add tests for new code 2020-01-15 12:10:52 -08:00
Felix Rieseberg bb8053d86d fix: Create a backup for the preload editor 2020-01-15 12:09:59 -08:00
Mark Lee 5efaa54255 feat: publish preload scripts to GitHub gists (#292)
* fix: update welcome tour to mention preload scripts
* chore: update doc comments
2020-01-14 13:41:57 -08:00
Felix Rieseberg b38507230d Merge pull request #291 from electron/update-deps
chore: Update various dependencies
2020-01-14 13:30:30 -08:00
Felix Rieseberg 7451083c70 test: Fix one more test case 2020-01-14 12:16:48 -08:00
Felix Rieseberg be46780674 build: Update tslint rules 2020-01-13 10:55:01 -08:00
Felix Rieseberg 99b5d067df build: Update stylelint 2020-01-13 10:54:25 -08:00
Felix Rieseberg f34eb225ea feat: Update fallback releases 2020-01-13 10:52:49 -08:00
Felix Rieseberg 18cc36a837 feat: Update blueprint 2020-01-13 10:52:23 -08:00
Felix Rieseberg da403e3cbd feat: Update various dependencies 2020-01-13 10:51:04 -08:00
Felix Rieseberg b4431cf426 Merge pull request #285 from electron/direct-fetch-builtins
refactor: directly pull Node.js builtins
2020-01-13 10:46:01 -08:00
Felix Rieseberg e714269b9b Merge pull request #286 from electron/fix-jest-transform
test: avoid transforming JSON files
2020-01-13 10:44:57 -08:00
Felix Rieseberg b9518a63f8 Merge pull request #287 from Loseshape0/patch-1
Update Years
2020-01-13 10:44:28 -08:00
Felix Rieseberg 0627801bb0 Merge pull request #288 from electron/allow-execution-flags
feat: allow users to specify cli flags
2020-01-13 10:43:57 -08:00
Shelley Vohr 3adeece64d spec: fix small test details 2020-01-06 10:52:07 -05:00
Shelley Vohr aed45078c5 spec: update execution settings snapshot 2020-01-06 10:39:10 -05:00
Shelley Vohr 55bfb0241b add handleExecutionFlagChange spec 2020-01-04 21:13:52 -05:00
Shelley Vohr 7e90679706 feat: allow users to specify cli flags 2020-01-04 10:46:59 -05:00
Loseshape0 4897bdbf84 Update Years 2020-01-01 17:41:48 -10:00
Mark Lee 7a02f8cacd test: avoid transforming JSON files 2019-12-27 22:49:16 -08:00
Shelley Vohr a65d594fbc refactor: directly pull Node.js builtins 2019-12-19 21:17:38 -08:00
Felix Rieseberg f32fce2f80 Merge pull request #281 from electron/fix-dropdowns
fix: Incorrect dropdowns
2019-12-12 14:56:25 -05:00
Felix Rieseberg 26e054702a fix: Incorrect dropdowns 2019-12-12 14:23:11 -05:00
Felix Rieseberg 16f27132cb Revert "First basis for having Node in there, too"
This reverts commit 7613176f69.
2019-12-12 14:06:34 -05:00
Felix RiesebergandTierney Cyren 7613176f69 First basis for having Node in there, too
Co-authored-by: Tierney Cyren <ticyren@microsoft.com>
2019-12-11 12:19:16 -05:00
dependabot[bot] 470bea4fca build(deps): bump serialize-to-js from 3.0.0 to 3.0.1 (#280)
Bumps [serialize-to-js](https://github.com/commenthol/serialize-to-js) from 3.0.0 to 3.0.1.
- [Release notes](https://github.com/commenthol/serialize-to-js/releases)
- [Commits](https://github.com/commenthol/serialize-to-js/compare/v3.0.0...v3.0.1)

Signed-off-by: dependabot[bot] <support@github.com>
2019-12-10 00:30:59 -08:00
Felix Rieseberg 363febdb73 Merge pull request #279 from electron/notarize
build: Notarize the build with Apple
2019-12-04 13:43:38 -08:00
Felix Rieseberg 062ca4e205 build: Update to electron-forge b46 2019-12-04 10:44:13 -08:00
Felix Rieseberg 49053342a5 Merge pull request #278 from electron/electron-713
chore: Update Electron to 7.1.3
2019-12-04 10:09:10 -08:00
Felix Rieseberg fd582c67a8 build: Use a later macOS image 2019-12-03 18:08:51 -08:00
Felix Rieseberg 706b18808b build: Notarize the build with Apple 2019-12-03 17:52:52 -08:00
Felix Rieseberg a6ae8d5376 chore: Update Electron to 7.1.3 2019-12-03 17:45:02 -08:00
Erick Zhao 5034f8c853 feat: add bisect helper (#257) 2019-11-22 18:46:58 -05:00
Letra e916247013 fix: ensure dev tools only open in dev mode (#277) 2019-11-15 09:22:14 -05:00
Felix Rieseberg c052686de4 0.11.1 2019-11-12 14:39:38 +01:00
Erick Zhao 31aacef131 fix: update folder selection dialog for Electron 7 (#271) 2019-11-05 16:51:04 -05:00
Erick Zhao 932369b705 fix: update deprecated app.setName API (#273) 2019-11-05 16:24:43 -05:00
Shelley Vohr b835c34786 fix: update dialog example for promisification (#272) 2019-11-03 11:36:00 -05:00
Felix Rieseberg c9e1ba815a 0.11.0 2019-10-31 11:49:23 -04:00
Felix Rieseberg 374a85e2f6 Merge pull request #267 from electron/updates-updates
feat: Electron 7 (and more updates)
2019-10-27 11:26:14 -07:00
Felix Rieseberg 4282d0b93d fix: Better typing 2019-10-27 11:16:55 -07:00
Felix Rieseberg 549862b3bb chore: npm audit fix 2019-10-27 11:13:02 -07:00
Felix Rieseberg 4691c1b494 chore: Use a lockfile with latest npm 2019-10-27 11:10:36 -07:00
Felix Rieseberg 8125abc657 build: Update AppVeyor to Node 12 2019-10-27 11:01:39 -07:00
Felix Rieseberg 8cba7739f5 fix: Prepare for Electron 7 2019-10-25 11:59:05 -07:00
Felix Rieseberg 0b39fe40b1 chore: Update all the packages 2019-10-25 11:37:34 -07:00
Felix Rieseberg cae078ffe6 Merge pull request #266 from electron/ignored-commented-out-modules
fix: don't install commented-out requires
2019-10-15 18:14:33 -07:00
Ankit Arun bfb931435f fix: add whitespace to Welcome Tour (#263) 2019-10-14 20:48:40 -04:00
Shelley Vohr c878f72f2e fix: don't install commented-out requires 2019-10-14 13:59:00 -07:00
Felix Rieseberg 32494c057a Merge pull request #254 from electron/preload
feat: Enable support for a `preload.js`
2019-10-05 14:52:58 -10:00
Jason Zeng e732685fff fix: link to docs for content tracing show-me (#256) 2019-09-25 10:16:44 -04:00
Felix Rieseberg d9d5e0cbc9 test: Fix the tests 2019-09-17 16:14:38 -07:00
Felix Rieseberg 0e1d7b541e feat: If a file is newly empty, remove it 2019-09-17 15:59:27 -07:00
Felix Rieseberg 8a602d94b7 feat: Enable support for a preload.js 2019-09-17 15:50:49 -07:00
Erick Zhao 155889dbcc fix: ensure state consistency when replacing Fiddle (#253) 2019-09-16 14:53:53 -04:00
Felix Rieseberg 56ac6662b6 Merge pull request #248 from electron/add-new-themes
feat: ability to add new editor themes to Fiddle
2019-09-10 13:40:08 -04:00
Felix Rieseberg adb196549b chore: Bump version to 0.10 2019-09-08 15:45:59 -07:00
Felix Rieseberg 999facf062 Merge pull request #250 from electron/fix-console-stuff
fix: Console button / display issues
2019-09-08 15:39:55 -07:00
Felix Rieseberg fa0115f2db fix: Correctly toggle console state 2019-09-08 15:29:15 -07:00
Carlos Valdez c0a4c0e48d remove unused import 2019-09-07 11:05:13 -05:00
Carlos Valdez 3a5d2205fe remove unused imports 2019-09-07 11:03:27 -05:00
Carlos Valdez 1083b8f859 add warning dialog 2019-09-07 11:03:11 -05:00
Carlos Valdez 252d4c1de6 remove old code (yikes) 2019-09-07 10:25:10 -05:00
Carlos Valdez 0c44d2c9e4 remove check 2019-09-05 23:54:11 -05:00
Carlos Valdez 5eebc06514 add if statement inside try catch 2019-09-05 18:27:04 -05:00
Carlos Valdez eac1423177 remove comment 2019-09-05 18:18:44 -05:00
Carlos Valdez ae88780281 remove comment 2019-09-05 18:07:56 -05:00
Carlos Valdez 4bf9d48d70 remove commet 2019-09-05 18:07:36 -05:00
Carlos Valdez df6d4b5a9a remove monaco from observable variable name 2019-09-05 17:41:49 -05:00
Carlos Valdez 68202e2b23 change file name and change import 2019-09-05 17:23:40 -05:00
Felix Rieseberg acd5b35ca1 fix: Console button / display issues 2019-08-31 07:07:20 -07:00
Felix Rieseberg fae1ca3138 Merge pull request #249 from electron/update-dependencies
chore: Update all dependencies
2019-08-31 00:25:17 +02:00
Felix Rieseberg bd220d2690 chore: Update more dependencies 2019-08-30 15:07:07 -07:00
Felix Rieseberg d31f1016b8 test: Update all the tests 2019-08-30 15:05:07 -07:00
Felix Rieseberg 3b52be0f79 chore: Update templates for Standard 2019-08-28 09:44:10 +02:00
Felix Rieseberg 0e11c56f7f chore: Update all dependencies 2019-08-28 09:43:52 +02:00
Carlos Valdez 8019981d1a missing ; 2019-08-19 13:29:09 -07:00
Carlos Valdez 403a58e216 update snapshot 2019-08-19 13:28:42 -07:00
Carlos Valdez 3341d0ccaa fix json parsing 2019-08-19 11:13:32 -07:00
Carlos Valdez d42e83100a need to work on successful input 2019-08-16 17:58:27 -07:00
Carlos Valdez 50e9883d82 add new popup using react! 😰 2019-08-16 17:37:22 -07:00
Carlos Valdez f5aedac6a3 change wording of import monaco themes and add better formatting 2019-08-15 11:09:13 -07:00
Carlos Valdez a3f4aa8ed3 remove old code 2019-08-15 10:02:30 -07:00
Carlos Valdez 9c839aaad8 remove sad code 2019-08-15 09:57:30 -07:00
Carlos Valdez 3a7ca8ccd5 Merge branch 'add-new-themes' of github.com:electron/fiddle into add-new-themes 2019-08-15 09:56:15 -07:00
Carlos Valdez fef42293bc account for user checking an incorrect file 2019-08-15 09:56:02 -07:00
Felix Rieseberg 1f9db42c80 Merge pull request #247 from electron/feat/local-version-intellisense
feat: intellisense for local builds
2019-08-14 14:51:18 -07:00
Carlos Valdez 8e5657ef2d the coolest recursive function thanks to Samuel 2019-08-14 13:34:43 -07:00
Carlos Valdez a94105dd27 the coolest recursive function thanks to Samuel 2019-08-14 13:34:29 -07:00
Carlos Valdez cf214dc0d0 remove bad method 2019-08-14 11:03:54 -07:00
Carlos Valdez 6dfdf00437 add in new function and button 2019-08-14 11:03:36 -07:00
Carlos Valdez b3743a4c73 Merge branch 'add-new-themes' of github.com:electron/fiddle into add-new-themes 2019-08-13 17:07:15 -07:00
Carlos Valdez 3c0d6c2293 fix my mess 2019-08-13 17:06:23 -07:00
CarlosandErick Zhao 89b589fd2e Update tests/renderer/components/__snapshots__/settings-general-appearance-spec.tsx.snap
Co-Authored-By: Erick Zhao <erick@hotmail.ca>
2019-08-13 16:53:48 -07:00
CarlosandErick Zhao 42c577988d Update src/renderer/components/settings-general-appearance.tsx
Co-Authored-By: Erick Zhao <erick@hotmail.ca>
2019-08-13 16:53:37 -07:00
CarlosandErick Zhao d0e47b6b4d Update src/renderer/components/settings-general-appearance.tsx
Co-Authored-By: Erick Zhao <erick@hotmail.ca>
2019-08-13 16:41:34 -07:00
CarlosandErick Zhao f44a127012 Update tests/renderer/components/__snapshots__/settings-general-appearance-spec.tsx.snap
Co-Authored-By: Erick Zhao <erick@hotmail.ca>
2019-08-13 16:41:22 -07:00
Carlos Valdez fa2f5454ce don't throw! 2019-08-13 11:24:12 -07:00
Carlos Valdez 1021bb8b2b remove console.warn 2019-08-13 10:34:40 -07:00
Carlos Valdez cf4ad36ca2 remove optional arg 2019-08-13 10:33:38 -07:00
Carlos Valdez 4fe9c627b5 if json has name, set that as the filename otherwise take the filename 2019-08-13 10:25:21 -07:00
Carlos Valdez 262e636e8d update snapshot 2019-08-12 17:53:26 -07:00
Carlos Valdez bbe79ed6e2 added description 2019-08-12 15:32:46 -07:00
Carlos Valdez bc96a5013a added new VS Code option 2019-08-12 15:32:37 -07:00
Erick Zhao 66ba7b74d5 test: add spec 2019-08-12 10:13:08 -07:00
Erick Zhao 38e5aa98e3 test: remove '.only' 2019-08-09 13:06:28 -07:00
Erick Zhao a91504b173 feat: local typedefs 2019-08-09 13:05:07 -07:00
Erick Zhao 4685e88c86 style: run linter 2019-08-09 11:27:08 -07:00
Erick Zhao e0bb82d919 fix: throw appropriately if cannot fetch types 2019-08-08 15:43:14 -07:00
Erick Zhao 7035be3286 fix: adjust styling to avoid hiding intellisense (#243) 2019-07-30 10:43:44 -07:00
Erick Zhao c961cfadb8 chore: merge in settings UX improvements 2019-07-30 10:43:10 -07:00
Erick Zhao 7267a2ee88 fix: load empty files upon opening a fiddle (#241)
* fix: load empty files upon opening a fiddle
* test: add spec for no value passed to setValue
2019-07-30 10:42:16 -07:00
Erick Zhao bc03382dc5 test: test for event listener removal upon unmount 2019-07-29 08:48:59 -07:00
Erick Zhao 891c33ba68 fix: refresh theme list upon creation 2019-07-28 20:02:35 -07:00
Erick Zhao e7260c74a4 feat: close settings panel on Esc 2019-07-28 20:02:35 -07:00
Erick Zhao ed694a7044 chore: describe correct component in spec 2019-07-28 20:02:35 -07:00
Erick Zhao 14fc77c08c chore: 'Exection' -> 'Execution' 2019-07-28 20:02:35 -07:00
Erick Zhao f3079648cf fix: clean up typedefs when removing binaries (#240) 2019-07-26 18:03:57 -07:00
Felix Rieseberg 7272ec7899 Merge pull request #239 from electron/fix/consistent-tab-size
fix: enforce 2-space indents in all editors
2019-07-26 10:25:46 -07:00
Erick Zhao ac9ac701f7 test: add spec for forced tab size 2019-07-25 13:16:56 -07:00
Erick Zhao 7fce572823 fix: enforce tab-size 2 2019-07-25 12:40:53 -07:00
Erick Zhao 6186a80dad chore: 'monoaco' -> 'monaco' (#238) 2019-07-25 11:53:20 -07:00
Mark Lee ade6576285 build: upgrade Electron Forge to 6.0.0-beta.42 (#234) 2019-07-17 23:22:06 -07:00
Felix Rieseberg 61c58277f3 Merge pull request #233 from electron/chore/toogle
chore: `toogle` -> `toggle`
2019-07-17 19:48:00 -07:00
Erick Zhao c361d34a6d chore: toogle -> toggle 2019-07-16 17:54:02 -07:00
Erick Zhao 5887a6615a Merge pull request #232 from electron/feat/protocol-force-electron-version
feat: force electron version when loading from example protocol
2019-07-16 10:34:05 -07:00
Erick Zhao 7ba4cf5be7 style: run linter 2019-07-15 16:47:36 -07:00
Erick Zhao 0daf872d2b chore: conflict resolution w/ confirm prompt 2019-07-15 16:34:05 -07:00
Erick Zhao 75ec8ee9b1 chore: merge in master 2019-07-15 16:24:00 -07:00
Erick Zhao 183c152e40 test: create spec for remote-loader 2019-07-15 16:18:04 -07:00
Erick Zhao d6a807ba41 refactor: move version checking to its own fn 2019-07-15 15:23:30 -07:00
Carlos 24e0abf667 Merge pull request #230 from electron/warning-prompt
feat: Warning prompt
2019-07-15 14:05:37 -07:00
Carlos Valdez eb8261e240 remove obsolete snapshot 2019-07-15 13:38:20 -07:00
Erick Zhao 84cc07da90 feat: load examples with specific electron version 2019-07-15 13:21:44 -07:00
Erick Zhao b0f3837b47 refactor: move remote loading to its own file 2019-07-15 13:20:56 -07:00
Carlos Valdez e29664ca45 fix added event spec 2019-07-15 13:18:55 -07:00
Carlos Valdez ef36ee39f6 - 2019-07-15 11:14:56 -07:00
Carlos Valdez 73dadb815e removed spec test 2019-07-15 11:14:45 -07:00
Carlos Valdez 4945501703 fix test spec 2019-07-15 11:02:08 -07:00
Erick Zhao 77c87fbdeb feat: console resizing (#226)
Adds a `react-mosaic` wrapper to the console component to enable resizing in a similar
fashion to the editor components.
2019-07-15 10:33:01 -07:00
Carlos Valdez 2ef5b42f4a solved conflicts on git rebase 2019-07-15 10:31:07 -07:00
Carlos Valdez 9c4bc2ba52 fix test-spec failing 2019-07-15 10:30:31 -07:00
Carlos Valdez 80da4e73e3 fixed specs 2019-07-15 10:30:31 -07:00
Carlos Valdez eadd58d149 fix test 2019-07-15 10:28:09 -07:00
Carlos Valdez 1fc82f8f6d update specs 2019-07-15 10:28:09 -07:00
CarlosandFelix Rieseberg 9bd7043b2c Update src/renderer/components/dialog-confirm.tsx
Co-Authored-By: Felix Rieseberg <felix@felixrieseberg.com>
2019-07-15 10:28:09 -07:00
Carlos aaeef6fd06 Update commands-address-bar.tsx 2019-07-15 10:28:09 -07:00
CarlosandFelix Rieseberg 1195902bd5 Update src/renderer/components/dialog-warning.tsx
Co-Authored-By: Felix Rieseberg <felix@felixrieseberg.com>
2019-07-15 10:28:09 -07:00
CarlosandFelix Rieseberg c022d0f33d Update src/renderer/components/dialog-warning.tsx
Co-Authored-By: Felix Rieseberg <felix@felixrieseberg.com>
2019-07-15 10:28:09 -07:00
CarlosandFelix Rieseberg 996ae775f3 Update src/renderer/components/commands-address-bar.tsx
Co-Authored-By: Felix Rieseberg <felix@felixrieseberg.com>
2019-07-15 10:28:09 -07:00
Carlos Valdez ed44dda8fb better label 2019-07-15 10:28:09 -07:00
Carlos Valdez effba13e73 add to dialog class 2019-07-15 10:28:09 -07:00
Carlos Valdez 65886c3b52 added dialog-confirm prompt for users 2019-07-15 10:28:09 -07:00
Carlos Valdez 8bd4dd366a fix test-spec failing 2019-07-15 10:16:46 -07:00
Erick Zhao 4e19578e34 feat: add support for unchecked release channels 2019-07-14 18:45:18 -07:00
Erick Zhao c7fd0bc95e feat: force electron version when load w/ protocol 2019-07-14 18:45:18 -07:00
Erick Zhao 29e2f03b1a feat: allow version utility fn to accept a string 2019-07-14 18:45:18 -07:00
Felix Rieseberg 4cd6f330da Merge pull request #227 from electron/deermichel/error-msg
chore: add offline notice when loading fiddles
2019-07-13 16:10:27 -07:00
Carlos Valdez 79521eac7c fixed specs 2019-07-12 16:03:28 -07:00
Carlos Valdez 2736499d68 fix test 2019-07-12 15:36:14 -07:00
Carlos Valdez 1cbb781e8d update specs 2019-07-12 15:25:02 -07:00
CarlosandFelix Rieseberg e849a49f6f Update src/renderer/components/dialog-confirm.tsx
Co-Authored-By: Felix Rieseberg <felix@felixrieseberg.com>
2019-07-12 14:48:40 -07:00
Carlos 0114d2c1eb Update commands-address-bar.tsx 2019-07-12 14:48:09 -07:00
CarlosandFelix Rieseberg 365537012f Update src/renderer/components/dialog-warning.tsx
Co-Authored-By: Felix Rieseberg <felix@felixrieseberg.com>
2019-07-12 14:45:00 -07:00
CarlosandFelix Rieseberg 3e435cb64d Update src/renderer/components/dialog-warning.tsx
Co-Authored-By: Felix Rieseberg <felix@felixrieseberg.com>
2019-07-12 14:44:55 -07:00
CarlosandFelix Rieseberg 6981382793 Update src/renderer/components/commands-address-bar.tsx
Co-Authored-By: Felix Rieseberg <felix@felixrieseberg.com>
2019-07-12 14:42:53 -07:00
Felix Rieseberg f293ba84d1 Merge pull request #229 from electron/feat/protocol-dev-mode-support
feat: add dev mode support for protocol
2019-07-12 14:41:05 -07:00
Carlos Valdez 55cf507a96 better label 2019-07-12 14:23:21 -07:00
Carlos Valdez e71c2439cd add to dialog class 2019-07-12 13:49:52 -07:00
Carlos Valdez 9bd253951c added dialog-confirm prompt for users 2019-07-12 13:49:40 -07:00
Erick Zhao eda08c9aea feat: change args passed in to support yarn
NPM and Yarn both forward arguments via `process.env.npm_config_argv`.
The URL would be in the `remain` property in NPM, but in `original`
in both NPM and Yarn.
2019-07-12 11:50:35 -07:00
Felix Rieseberg 9414f66893 Merge pull request #228 from electron/no-prerelease
build: Don't mark releases as prereleases
2019-07-12 11:44:40 -07:00
Erick Zhao f4725b5dd8 feat: add dev mode support for protocol 2019-07-12 11:35:18 -07:00
Felix Rieseberg fd8be47494 build: Don't mark releases as prereleases 2019-07-12 11:10:09 -07:00
Micha Hanselmann 2cebe2ca7c add more verbose msg when offline 2019-07-12 11:07:51 -07:00
Felix Rieseberg 74135bab67 0.9.0 2019-07-08 10:53:09 -07:00
Felix Rieseberg a856340d01 Merge pull request #225 from electron/update-dependencies
chore: Update the dependencies
2019-07-08 10:52:25 -07:00
Felix Rieseberg bd8939c358 chore: Update the dependencies 2019-07-07 17:15:43 -07:00
Felix Rieseberg 9d3f3d61eb Merge pull request #222 from erickzhao/fix/browserwindow-showme-script
fix: correct button code for BrowserWindow show-me
2019-07-06 12:46:07 -07:00
Felix Rieseberg bdeaffcb7d Merge pull request #223 from DeerMichel/deermichel/nightlies
fix: fetch nightlies from `electron-nightlies` channel
2019-07-06 12:45:40 -07:00
Andrew Cherniavskii 344e1df375 fix: console message in powermonitor example 2019-07-06 09:34:03 -07:00
Micha Hanselmann d5b52dcae7 fix nightlies fetch 2019-07-05 13:48:07 -07:00
Erick Zhao 0faeb24761 fix: correct button code for BrowserWindow show-me 2019-07-03 15:23:07 -07:00
Micha Hanselmann 284b579d0c fix out-of-scope tray ref (#221) 2019-07-03 11:14:39 -05:00
Felix Rieseberg 5a1c24cdda Merge pull request #220 from erickzhao/feat/publish-ux-fixes
feat: clarify UX for Publish Gist feature
2019-07-02 10:13:02 -07:00
Erick Zhao 024d48a273 test: add spec for publishing gist disabled form 2019-07-01 22:54:44 -07:00
Erick Zhao 32155d652d chore: update enzyme version 2019-07-01 22:54:04 -07:00
Erick Zhao 874a8bb0f0 test: Move isPublishing from local state to store 2019-07-01 21:15:18 -07:00
Erick Zhao 73470640c7 test: Update snapshots to match DOM changes 2019-07-01 21:15:18 -07:00
Erick Zhao 679f731f4c chore: Consistent use of "publish" keyword 2019-07-01 21:15:18 -07:00
Erick Zhao a41ad11f8c chore: Remove "public" from gist setting callout
Users can either set their published Gists as public or private, so it's
best to remove the "public" qualifier from the callout.
2019-07-01 21:15:18 -07:00
Erick Zhao 7cc6d38dc2 feat: Disable fields while publishing gists 2019-07-01 21:15:18 -07:00
Felix Rieseberg 1e6ee7ab37 Merge pull request #216 from drewswaycool/add-missing-spaces
adds missing spaces
2019-06-27 15:43:25 -07:00
Felix Rieseberg c50c31ad80 Merge pull request #219 from electron/bypass-contributor-check
build: Don't throw if missing contributors in PR
2019-06-27 15:35:20 -07:00
Felix Rieseberg 5f8557fb13 build: Don't throw if missing contributors in PR 2019-06-24 19:51:34 -07:00
Felix Rieseberg 47b20fa3e4 Merge pull request #218 from DeerMichel/deermichel/clear-console
feat: add ability to clear console output
2019-06-24 19:47:21 -07:00
Micha Hanselmann b5c8ed60a9 remove clear console top bar button 2019-06-17 21:16:23 -07:00
Micha Hanselmann 5e3d382b85 minor style fix 2019-06-17 09:41:57 -07:00
Micha Hanselmann fed0107dd1 i'm a contributer now... 2019-06-16 00:11:31 -07:00
Micha Hanselmann ca9b9c633a add clear-on-run test 2019-06-15 23:50:36 -07:00
Micha Hanselmann fb4c6b3f33 add ui tests for console settings 2019-06-15 23:38:29 -07:00
Micha Hanselmann aa51c0cc5c implement clear on run 2019-06-15 23:28:20 -07:00
Micha Hanselmann e5236c5500 add settings ui for clear-on-run option 2019-06-15 23:22:49 -07:00
Micha Hanselmann 321f7a8bbc fix top bar buttons test 2019-06-15 23:02:28 -07:00
Micha Hanselmann 1ff7a3fe16 fix context menu test 2019-06-15 23:00:04 -07:00
Micha Hanselmann a1c74c018d add test for clearConsole 2019-06-15 22:53:48 -07:00
Micha Hanselmann 5df39ea51a add context menu entry to clear console 2019-06-15 22:41:44 -07:00
Micha Hanselmann 8a9591be9f add clear console button to top bar 2019-06-15 22:37:25 -07:00
Micha Hanselmann 3cc8fd41f6 add clearConsole method 2019-06-15 22:29:32 -07:00
Drew McMurry 25df3dd989 adds missing spaces 2019-06-14 15:38:39 -06:00
Felix Rieseberg abe7bdab23 Merge pull request #213 from electron/fix-touch-bar-example
fix: correct touch bar constructor in example
2019-06-11 21:16:44 -04:00
Shelley Vohr 16bea01ba5 fix: correct touch bar constructor in example 2019-06-11 14:17:44 -07:00
Felix Rieseberg 7417a82931 0.8.1 2019-06-11 11:35:40 -04:00
Felix Rieseberg 4c41db8595 Merge pull request #212 from electron/no-download-test
test: Mock electron-download
2019-06-11 17:35:23 +02:00
Felix Rieseberg 5da87ffca3 Merge pull request #211 from electron/fix-menu
fix: Don't attempt to set about panel on Windows
2019-06-11 17:05:07 +02:00
Felix Rieseberg 919e9cb6b6 test: Mock electron-download 2019-06-11 11:02:09 -04:00
Felix Rieseberg 14279283d6 fix: Don't attempt to set about panel on Windows 2019-06-11 10:51:42 -04:00
Felix Rieseberg 77a98112a1 Merge pull request #209 from amorist/fix-submit-token
Fix: submit token
2019-06-11 16:43:05 +02:00
amorist 08fb3f52bf fixed submit token 2019-06-11 14:27:47 +08:00
Felix Rieseberg b37ba895e5 0.8.0 2019-06-10 12:09:48 -04:00
Felix Rieseberg 33a236edd1 Merge pull request #203 from electron/load-electron-examples
feat: add support for launch examples from the Electron docs
2019-06-07 21:30:27 +02:00
Felix Rieseberg f7930fb523 test: Fix more tests 2019-06-07 12:15:49 -07:00
Felix Rieseberg 88cad66076 test: Add some tests 2019-06-07 11:01:36 -07:00
Felix Rieseberg f0afedf896 fix: Linter issues 2019-06-07 09:39:36 -07:00
Samuel Attard 38234dd0a3 chore: fix specs 2019-06-06 14:59:53 -07:00
Felix Rieseberg 83e834bea5 Merge pull request #205 from electron/touchbar
feat: Touchbar
2019-06-06 18:23:18 +02:00
Felix Rieseberg 38be3cca14 test: Add touchBarManager creation 2019-06-03 15:59:00 -07:00
Felix Rieseberg 4908cc6110 feat: Sort versions in touch bar 2019-06-03 13:11:11 -07:00
Felix Rieseberg ab4a9015d1 feat: Add a touchbar feature 2019-06-02 21:12:34 -07:00
Felix Rieseberg 73ab813efc Merge pull request #204 from electron/add-about-panel
feat: add more information to about panel
2019-06-02 09:30:00 +02:00
Shelley Vohr f3570c5069 spec: add a spec for about panel functionality 2019-06-01 09:54:25 -07:00
Shelley Vohr 4c564eaa63 feat: add more information to about panel 2019-05-31 22:32:05 -07:00
Samuel Attard a289842e32 feat: add support for launch examples from the Electron docs 2019-05-27 11:03:18 -07:00
Felix Rieseberg 9d697e7a3f Merge pull request #202 from electron/gist-launch
feat: add wiring for protocol launching gists
2019-05-27 00:16:51 -07:00
Felix Rieseberg e96e5345e6 Merge pull request #201 from electron/fix-audit
chore: fix npm audit output
2019-05-27 00:16:00 -07:00
Samuel Attard 7c97bc2ef6 feat: add wiring for protocol launching gists 2019-05-25 15:29:04 -07:00
Samuel Attard d55c5c067d chore: fix npm audit output 2019-05-25 14:08:14 -07:00
Felix Rieseberg 083ac3fbc2 chore: Update monaco-loader 2019-05-17 17:23:47 +09:00
Felix Rieseberg 5c8fe3d6e0 build: Fix x64 releases 2019-05-17 14:00:54 +09:00
Felix Rieseberg f034c5240c chore: Update version number 2019-05-17 13:29:40 +09:00
Felix Rieseberg 6421187db4 Merge pull request #197 from electron/editors-to-panels
feat: Panels
2019-05-17 13:00:26 +09:00
Felix Rieseberg 6fb385a95f fix: Import typo 2019-05-17 12:39:14 +09:00
Felix Rieseberg c47fea09ed fix: Don't whine plz 2019-05-17 12:31:10 +09:00
Felix Rieseberg ef17ccd9cb test: Update the tests 2019-05-17 12:31:10 +09:00
Felix Rieseberg 3f173aa4d4 chore: Better panel titles 2019-05-17 12:31:10 +09:00
Felix Rieseberg faf15081e0 fix: Fix linter issues 2019-05-17 12:31:10 +09:00
Felix Rieseberg 4306f53c70 feat: A first demo 2019-05-17 12:31:10 +09:00
Felix Rieseberg 52a8aac6c7 test: Add a test for the default show-me page 2019-05-17 12:31:10 +09:00
Felix Rieseberg 7660192dcb test: Update the tests 2019-05-17 12:31:10 +09:00
Felix Rieseberg 53ceeb5600 feat: New overview button for docs & demos 2019-05-17 12:31:10 +09:00
Felix Rieseberg 5cd7a57f08 feat: Basic implementation of demo pages 2019-05-17 12:31:10 +09:00
Felix Rieseberg e96a3da09b feat: A generic "this is a subset only" component 2019-05-17 12:31:10 +09:00
Felix Rieseberg 90c198d487 feat: A generic "more information" component 2019-05-17 12:31:10 +09:00
Felix Rieseberg 5b56333516 feat: A utility to get docs urls 2019-05-17 12:31:10 +09:00
Felix Rieseberg c87f65ca76 feat: A generic show me component 2019-05-17 12:31:10 +09:00
Felix Rieseberg 0f27c8aa7a fix: Typo in type-checks 2019-05-17 12:31:10 +09:00
Felix Rieseberg b5880aef46 feat: Give docs their own little button 2019-05-17 12:31:10 +09:00
Felix Rieseberg fb46eaf0e4 feat: Improve panel styles 2019-05-17 12:31:10 +09:00
Felix Rieseberg c1040097e3 fix: A small issue with panel visibility 2019-05-17 12:31:10 +09:00
Felix Rieseberg 333758b73d feat: Basic awareness of opened template 2019-05-17 12:31:10 +09:00
Felix Rieseberg 3c2a4e1b76 test: Improve the tests, cover more 2019-05-17 12:31:10 +09:00
Felix Rieseberg f3d42c107f test: Add test for type check 2019-05-17 12:31:10 +09:00
Felix Rieseberg 2ece4dc728 feat: Editors to Panels, for real 2019-05-17 12:31:10 +09:00
Felix Rieseberg dd2975bd0e feat: Add the ability to render generic panels 2019-05-17 12:31:10 +09:00
Felix Rieseberg fdf03dff9b Merge pull request #198 from electron/updates
feat: Update all dependencies (Electron 5)
2019-05-17 12:30:44 +09:00
Felix Rieseberg 48fa762f7f build: Fine, Node v10 it is >:( 2019-05-17 12:16:26 +09:00
Felix Rieseberg 7cd9a86920 fix: Appease AppVeyor 2019-05-17 12:12:30 +09:00
Felix Rieseberg db2caaad59 feat: Update all dependencies (Electron 5) 2019-05-17 12:09:49 +09:00
Felix Rieseberg 3b2cb93d8b Merge pull request #195 from ajphukan/require-not-defined-bug
Fix: Require not defined bug
2019-05-16 10:58:49 +09:00
Ankur Jyoti Phukan 9822753ffd Update contributors.js 2019-05-09 12:54:48 +05:30
Ankur Jyoti Phukan 8712907182 Removed trailing space 2019-05-09 12:40:00 +05:30
Ankur Jyoti Phukan 40055ee069 Removed trailing space 2019-05-09 12:38:53 +05:30
Ankur Jyoti Phukan a33f175867 Removed trailing space 2019-05-09 12:38:11 +05:30
Ankur Jyoti Phukan 107ba63a5a Removed trailing spcae 2019-05-09 12:36:56 +05:30
Ankur Jyoti Phukan b66ad7e247 Removed trailing space 2019-05-09 12:36:20 +05:30
Ankur Jyoti Phukan 7eb15b6666 Removed Trailing space 2019-05-09 12:35:43 +05:30
Ankur Jyoti Phukan 2ed29f68dd Update main.js 2019-05-09 12:34:46 +05:30
Ankur Jyoti Phukan d89d595b57 Removed Trailing Space 2019-05-09 12:29:07 +05:30
Ankur Jyoti Phukan 2b34ef5e67 Update main.js 2019-05-09 12:23:08 +05:30
Ankur Jyoti Phukan d6f7146447 Update main.js 2019-05-09 12:22:32 +05:30
Ankur Jyoti Phukan 006ba5f0a5 Update main.js 2019-05-09 12:21:55 +05:30
Ankur Jyoti Phukan 5df390b0fd Update main.js 2019-05-09 12:21:13 +05:30
Ankur Jyoti Phukan 3eb25fed91 Update main.js 2019-05-09 12:20:21 +05:30
Ankur Jyoti Phukan 9b06f792ea Update main.js 2019-05-09 12:19:50 +05:30
Ankur Jyoti Phukan c116152605 Update main.js 2019-05-09 12:19:33 +05:30
Ankur Jyoti Phukan b9f8d55809 Update main.js 2019-05-09 12:19:13 +05:30
Ankur Jyoti Phukan 89e697fcd6 Update main.js 2019-05-09 12:18:53 +05:30
Ankur Jyoti Phukan 9df5314c08 Update main.js 2019-05-09 12:17:43 +05:30
Ankur Jyoti Phukan d01ba1cdff Added webPreference 2019-05-09 12:01:19 +05:30
Ankur Jyoti Phukan ed5ccf133f Added webPreference 2019-05-09 12:00:28 +05:30
Ankur Jyoti Phukan e1decd4819 Added webPreference 2019-05-09 11:59:49 +05:30
Ankur Jyoti Phukan 3c9f477b89 Added webPreference 2019-05-09 11:57:22 +05:30
Ankur Jyoti Phukan 5cfbf2cab5 Added webPreference 2019-05-09 11:56:36 +05:30
Ankur Jyoti Phukan 89272fbaa9 Added webPreference 2019-05-09 11:55:47 +05:30
Ankur Jyoti Phukan 5d572f451c Added webPreference 2019-05-09 11:54:52 +05:30
Ankur Jyoti Phukan 319136ecc8 Added WebPreference 2019-05-09 11:51:08 +05:30
Ankur Jyoti Phukan 3a4aa06331 Added WebPreference 2019-05-09 11:48:17 +05:30
Felix Rieseberg e283a118f6 Merge pull request #187 from malept/update-forge-transform
fix: use the latest version of Forge v6 for Fiddle Forge actions
2019-04-12 11:44:24 -07:00
Mark Lee e67d1b0179 fix: use the latest version of Forge v6 for Fiddle Forge actions 2019-04-10 23:28:42 -07:00
Felix Rieseberg 9805d98dd8 Merge pull request #184 from electron/test-100
test: Ensure full coverage
2019-04-02 16:11:20 -07:00
Felix Rieseberg 009ad25983 test: Test GitHub authentication in address bar 2019-04-02 15:52:23 -07:00
Felix Rieseberg 9a65124289 test: Test editors with visible editors 2019-04-02 15:39:44 -07:00
Felix Rieseberg 4d7c81ee69 Merge pull request #183 from electron/panel-management
feat: Panel management (close and open editors)
2019-04-02 15:27:06 -07:00
Felix Rieseberg ed91cb5ba1 test: Increase test coverage 2019-04-01 16:23:17 -07:00
Felix Rieseberg 8b04f67f71 fix: Linting issues 2019-04-01 16:15:34 -07:00
Felix Rieseberg 2e183f0538 fix: Handle setting values on closed editors 2019-04-01 16:13:51 -07:00
Felix Rieseberg 6b022bbea7 test: Improve the tests 2019-04-01 15:54:03 -07:00
Felix Rieseberg 6bdb7d71ec feat: Add a non-ideal state for the editors 2019-03-31 17:31:22 -07:00
Felix Rieseberg 0ebe6ab9b3 fix: Style when there is only one panel 2019-03-31 16:24:05 -07:00
Felix Rieseberg 5e73deeb4f test: Polish and lint tests 2019-03-31 14:04:24 -07:00
Felix Rieseberg 02d81aa407 test: Add spec for the new state methods 2019-03-31 13:59:20 -07:00
Felix Rieseberg 46deeb857e test: Test editors-mosaic-arrangement 2019-03-31 13:35:34 -07:00
Felix Rieseberg ca55d2e620 test: Add a spec for editors-toolbar-button 2019-03-31 13:07:36 -07:00
Felix Rieseberg 88974d277f test: Update the editor spec 2019-03-31 13:01:06 -07:00
Felix Rieseberg 1239afafeb test: Add spec for commands-editor 2019-03-31 12:45:36 -07:00
Felix Rieseberg 415877c067 test: Add spec for devtools 2019-03-31 12:24:54 -07:00
Felix Rieseberg 0a0779ffa1 test: Add tests for the new editor utilities 2019-03-31 12:17:46 -07:00
Felix Rieseberg 9cf34ea983 test: Fix the existing tests 2019-03-31 12:06:04 -07:00
Felix Rieseberg 83a7d23b38 test: Fix Wallaby & Jest 2019-03-31 12:00:09 -07:00
Felix Rieseberg 7d19ad91a6 feat: Add panel management 2019-03-31 10:39:56 -07:00
Felix Rieseberg db13699790 feat: Install dev tools 2019-03-31 10:36:55 -07:00
Felix Rieseberg 4a8fc24ff6 fix: Version number test 2019-03-30 17:02:39 -07:00
Felix Rieseberg 3ed41626b1 chore: Update version, electron versions 2019-03-28 09:29:44 -07:00
Felix Rieseberg b3e25cfe79 Merge pull request #182 from electron/electron-logging
feat: add an execution toggle to enable advanced electron logging
2019-03-27 15:15:49 -07:00
Samuel Attard 00bb15a891 feat: add an execution toggle to enable advanced electron logging 2019-03-27 11:02:12 -07:00
Felix Rieseberg 94da51128a Merge pull request #181 from electron/update-dependencies
feat: Update all dependencies
2019-03-25 14:51:43 -04:00
Felix Rieseberg b573f09494 fix: Lockfile was somehow out of sync 2019-03-25 10:19:51 -07:00
Felix Rieseberg f05e36de34 infra: Update all dependencies 2019-03-25 10:17:14 -07:00
Felix Rieseberg 44c7c70793 Merge pull request #178 from electron/bump-version-06
build: Update the version number
2019-02-22 11:54:49 +00:00
Felix Rieseberg bcbca7aceb build: Update the version number 2019-02-22 11:54:34 +00:00
Felix Rieseberg 9515458545 Merge pull request #177 from electron/electron-405
build: Update to Electron 4.0.5
2019-02-22 11:53:45 +00:00
Felix Rieseberg 219e90cad8 build: Update to Electron 4.0.5 2019-02-22 11:44:27 +00:00
Felix Rieseberg ba23c8019d Merge pull request #175 from electron/update-octokit
feat: Update octokit, handle fiddle load errors
2019-02-22 11:42:18 +00:00
Felix Rieseberg 2fef96a2b2 Merge branch 'master' into update-octokit 2019-02-22 11:31:15 +00:00
Felix Rieseberg 2d8cb9748d Merge pull request #176 from electron/update-dependencies-2
build: Update all the dependencies
2019-02-22 11:30:38 +00:00
Felix Rieseberg eaefbb7ad0 infra: Update all the dependencies 2019-02-21 11:32:11 +00:00
Felix Rieseberg d5f28253f8 feat: Handle loadFiddle() errors 2019-02-21 11:15:50 +00:00
Felix Rieseberg ac451d6b4a infra: Update Octokit methods 2019-02-21 11:01:03 +00:00
Felix Rieseberg b5e0e63766 infra: Update Octokit 2019-02-21 11:00:50 +00:00
Felix Rieseberg 49538ea55a Merge pull request #174 from electron/fix-show-me
fix: Lower-case names for show-me-templates
2019-02-21 10:26:16 +00:00
Felix Rieseberg 23ac9b8e02 fix: Lower-case names for show-me-templates 2019-02-20 16:27:47 +00:00
Felix Rieseberg 4bf2bee7c8 docs: Update the readme with new screenshot 2019-02-01 16:44:58 -08:00
Felix Rieseberg e742d8426c Merge pull request #172 from electron/fix-contributors-script
fix: Allow contributors.js to use GitHub credentials
2019-02-01 15:54:38 -08:00
Felix Rieseberg 7a223fd3dc fix: Allow contributors.js to use GitHub credentials 2019-02-01 15:14:41 -08:00
Felix Rieseberg 6bdc995eb6 Merge pull request #170 from electron/feat-158
feat: Display only Electron versions with a certain state
2019-01-30 22:07:35 -08:00
Felix Rieseberg 72cbcd46d1 test: Update one last test 2019-01-30 21:55:18 -08:00
Felix Rieseberg f1e51c71a3 Merge pull request #171 from electron/properly-quit
fix: On quit, quit properly
2019-01-29 19:01:28 -08:00
Felix Rieseberg 95e88c0eee test: Fix tests 2019-01-27 00:25:26 -08:00
Felix Rieseberg a54037ef0e test: Update snapshot 2019-01-26 19:15:26 -08:00
Felix Rieseberg 83bb6fc73e test: Add more tests, 2019-01-26 19:10:15 -08:00
Felix Rieseberg f8f1f0ec08 fix: On quit, quit properly 2019-01-26 18:59:40 -08:00
Felix Rieseberg f7a19b92a8 Merge pull request #169 from electron/more-enoent-logging
fix: Add some detailed templates logging
2019-01-26 18:39:55 -08:00
Felix Rieseberg dc76b78337 feat: Include it in the version chooser 2019-01-26 18:39:28 -08:00
Felix Rieseberg f6f3e94a97 feat: Add a setting for states to show 2019-01-26 18:36:34 -08:00
Felix Rieseberg 89cede25b1 Merge pull request #168 from electron/fix-167
fix: Correctly load Fiddle without form submit
2019-01-26 18:15:12 -08:00
Felix Rieseberg 8e8eec3cc6 fix: Add some detailed templates logging 2019-01-26 18:14:15 -08:00
Felix Rieseberg a0d8ca4019 fix: Correctly load Fiddle without form submit 2019-01-26 17:58:42 -08:00
Felix Rieseberg 1f0581afbc Merge pull request #166 from electron/bump-version-050
chore: Bump version to 0.5.0
2019-01-23 12:44:07 -08:00
Felix Rieseberg 70d4902b87 chore: Bump version to 0.5.0 2019-01-22 17:37:12 -08:00
Felix Rieseberg a93a99e3f0 Merge pull request #165 from electron/electron-4
feat: Update to Electron 4
2019-01-22 17:32:10 -08:00
Felix Rieseberg 4c209159e6 chore: jk, 4.0.2 2019-01-22 17:21:34 -08:00
Felix Rieseberg b09a248c96 feat: Update to Electron 4 2019-01-22 17:04:29 -08:00
Felix Rieseberg 6f09ed9c2a Merge pull request #163 from electron/forge-6-b32
chore: update Electron Forge to 6.0.0-beta.32
2019-01-21 12:51:56 -08:00
Felix Rieseberg c1ae0ecd86 Merge pull request #162 from electron/miniak/node-integration
feat: support upcoming Electron 5.0 with nodeIntegration disabled by default
2019-01-21 12:51:17 -08:00
Mark Lee 1e9a81fcf4 chore: update Electron Forge to 6.0.0-beta.32 2019-01-16 16:37:40 -08:00
Milan Burda 2061b26ed6 feat: support upcoming Electron 5.0 with nodeIntegration disabled by default 2019-01-16 20:10:52 +01:00
Felix Rieseberg 88ce4a76e9 Merge pull request #160 from bpasero/bpasero-run-f5
feat: Allow to run a fiddle via F5
2019-01-11 14:40:49 -08:00
Benjamin Pasero 9b4ef4c0d2 Allow to run a fiddle via F5
Enables to run a fiddle just with the keyboard.
2019-01-11 11:50:13 +01:00
Felix Rieseberg dca2cd67e5 Merge pull request #156 from electron/mac-better-frame
feat: support double click action on custom mac window title
2019-01-10 14:18:56 -08:00
Samuel Attard 6bab353088 fix: properly animate the opening / closing of the terminal 2019-01-09 13:44:10 +13:00
Samuel Attard e6cc44ca37 feat: support double click action on the window title bar on macOS 2019-01-09 13:43:55 +13:00
Felix Rieseberg d039c5dbf5 Merge pull request #155 from electron/bump-version-042
chore: Bump version to 0.4.2
2019-01-08 12:31:30 -08:00
Felix Rieseberg c155fff8b0 chore: Bump version to 0.4.2 2019-01-08 11:40:45 -08:00
Felix Rieseberg 11202a8d6b Merge pull request #152 from electron/100-coverage
test: Full unit test coverage
2019-01-08 11:38:52 -08:00
Felix Rieseberg 475127f5b1 fix: Travis coverage report 2019-01-08 11:17:13 -08:00
Felix Rieseberg feee5be2f8 test: Improve coverage, fix report 2019-01-08 11:11:56 -08:00
Felix Rieseberg 678c7f1578 chore: Fix coverage report 2019-01-08 10:54:59 -08:00
Felix Rieseberg d2fcb8071b test: Correctly report error 2019-01-07 23:18:57 -08:00
Felix Rieseberg 0ab35dc867 test: Update snapshot 2019-01-07 23:16:07 -08:00
Felix Rieseberg 377d221191 chore: Final cleanup 2019-01-07 23:09:42 -08:00
Felix Rieseberg cbdab9d662 test: Cover all of exec 2019-01-07 23:09:42 -08:00
Felix Rieseberg 6875ab392e test: Cover all of versions 2019-01-07 23:09:42 -08:00
Felix Rieseberg 58ec0f015c test: Cover all of file-manager 2019-01-07 23:09:42 -08:00
Felix Rieseberg 2aef0e776e test: Cover all of app 2019-01-07 23:09:42 -08:00
Felix Rieseberg b2a7d6b2a4 test: Cover all of tour 2019-01-07 23:09:42 -08:00
Felix Rieseberg 303d6bc79a test: Cover all of tour-welcome 2019-01-07 23:09:42 -08:00
Felix Rieseberg d028e7c915 test: Cover all of settings-general-appearance 2019-01-07 23:09:42 -08:00
Felix Rieseberg f04631b6c1 test: Linting, cleanup 2019-01-07 23:09:42 -08:00
Felix Rieseberg c1bb524b59 test: Cover all of settings-electron 2019-01-07 23:09:42 -08:00
Felix Rieseberg 4a38fda293 test: Cover all of editors 2019-01-07 23:09:42 -08:00
Felix Rieseberg b98ad2b572 test: Cover all of dialog-token 2019-01-07 23:09:42 -08:00
Felix Rieseberg 6118b94b09 test: Cover all of add-version 2019-01-07 23:09:42 -08:00
Felix Rieseberg d0c1ee1a82 test: Cover all of publish-button 2019-01-07 23:09:42 -08:00
Felix Rieseberg 525715a911 test: Cover all of address-bar 2019-01-07 23:09:42 -08:00
Felix Rieseberg afbc0c9e6c test: Cover squirrel 2019-01-07 23:09:42 -08:00
Felix Rieseberg c1a9cdf88b chore: Add linter 2019-01-07 23:09:42 -08:00
Felix Rieseberg d281e61b8a test: Cover shared-constants (lol) 2019-01-07 23:09:42 -08:00
Felix Rieseberg 2fbbc10497 test: Cover update 2019-01-07 23:09:42 -08:00
Felix Rieseberg e8226ca97d test: Cover all of protocol 2019-01-07 23:09:42 -08:00
Felix Rieseberg 08f2dbe937 test: Cover all of menu 2019-01-07 23:09:42 -08:00
Felix Rieseberg 68813edb51 test: Cover all of main 2019-01-07 23:09:42 -08:00
Felix Rieseberg a32261414b test: Cover all of ipcMainManager 2019-01-07 23:09:42 -08:00
Felix Rieseberg 42f67e7b21 test: Cover all of first-run 2019-01-07 23:09:41 -08:00
Felix Rieseberg 7d9b0ed79d fix: Use localecompare for invalid versions 2019-01-07 23:09:41 -08:00
Felix Rieseberg 47f1b5c4c3 test: Cover all of files 2019-01-07 23:09:41 -08:00
Felix Rieseberg 432322694d test: Correctly use "it" 2019-01-07 23:09:41 -08:00
Felix Rieseberg 889e76cbae test: Cover all of output 2019-01-07 23:09:41 -08:00
Felix Rieseberg 4a689e5c06 test: Cover all of settings-credtis 2019-01-07 23:09:41 -08:00
Felix Rieseberg 3113f324cc test: Cover all of npm 2019-01-07 23:09:41 -08:00
Felix Rieseberg 64addb1fb0 test: Cover all of state 2019-01-07 23:09:41 -08:00
Felix Rieseberg e6facf60c1 test: Cover all of runner & binary 2019-01-07 23:09:41 -08:00
Felix Rieseberg 00cb5cf6c6 Merge pull request #151 from electron/different-constants
fix: Don't require all of electron
2019-01-07 00:39:19 +08:00
Felix Rieseberg 3e8dbebe42 Merge pull request #150 from electron/update-dependencies
feat: Update Electron, Monaco, React, and others
2019-01-07 00:30:24 +08:00
Felix Rieseberg dcdef4aa4e fix: One more incorrect import 2019-01-07 00:25:25 +08:00
Felix Rieseberg 590389abdc fix: Update tests 2019-01-07 00:14:37 +08:00
Felix Rieseberg 18a8f0c142 fix: Deal with incorrect types 2019-01-07 00:10:44 +08:00
Felix Rieseberg a8e8ab6f04 fix: Don't require all of electron 2019-01-07 00:05:17 +08:00
Felix Rieseberg 45ed35467a feat: Update react-mosaic-component 2019-01-06 23:47:36 +08:00
Felix Rieseberg eb49cb296a feat: Update to Electron 3.0.14 2019-01-06 23:39:48 +08:00
Felix Rieseberg c2344d50d2 feat: Update dependencies 2019-01-06 23:33:32 +08:00
Felix Rieseberg 7786e113d9 Merge pull request #148 from electron/fix-defaultversion
fix: Ensure correct version selection & display
2019-01-06 22:58:05 +08:00
Felix Rieseberg f8b51870d8 Merge pull request #146 from electron/use-classnames
refactor: Use classnames module
2019-01-06 21:51:46 +08:00
Felix Rieseberg 601c28dcf8 fix: Handle EEXIST in unzipper 2019-01-06 21:47:25 +08:00
Felix Rieseberg 49379af856 feat: Display "checking status" in run button 2019-01-06 21:47:11 +08:00
Felix Rieseberg 8347f79756 fix: Correctly choose defaultVersion 2019-01-06 21:32:21 +08:00
Felix Rieseberg c102128d5a infra: Use classnames module 2019-01-06 21:01:42 +08:00
Felix Rieseberg fcff053136 Merge pull request #145 from electron/coverage-report
test: Add coverage reports
2019-01-06 20:27:06 +08:00
Felix Rieseberg c3641cfa04 test: Add coverage reports 2019-01-06 20:09:21 +08:00
Felix Rieseberg 6eba3cbdcc Merge pull request #143 from electron/more-tests-2
test: Write even more tests
2019-01-06 19:57:47 +08:00
Felix Rieseberg 6393c59d5c test: One more app spec 2019-01-04 23:56:53 +08:00
Felix Rieseberg 543e86bc91 chore: Fix linter issue 2019-01-04 20:38:34 +08:00
Felix Rieseberg ea5fdd426c test: Add an app setup() spec 2019-01-04 20:33:45 +08:00
Felix Rieseberg fecc499cc5 test: Add an exec test case 2019-01-04 20:13:07 +08:00
Felix Rieseberg 8d0a1524b9 test: Remove impossible case in focused-editor 2019-01-04 20:12:58 +08:00
Felix Rieseberg 918e91965a test: Add a version spec 2019-01-04 19:59:38 +08:00
Felix Rieseberg 15bab9ff86 chore: Fix linter issues 2019-01-04 19:49:37 +08:00
Felix Rieseberg 7d879b59cf test: Add runner specs 2019-01-04 19:42:33 +08:00
Felix Rieseberg 72f7e058d6 test: Add some state tests 2019-01-04 19:26:07 +08:00
Felix Rieseberg a65e044b5c test: Add some file manager tests 2019-01-04 17:13:41 +08:00
Felix Rieseberg a4c4590816 test: Remove obselete snapshot 2019-01-04 16:58:14 +08:00
Felix Rieseberg 6fbb816be3 test: Add MockState 2019-01-04 16:56:32 +08:00
Felix Rieseberg ae0ba026f2 test: More setting tests 2019-01-04 16:56:27 +08:00
Felix Rieseberg cc2a44d10a test: More app tests 2019-01-04 16:56:03 +08:00
Felix Rieseberg 3e6eb16974 Merge pull request #142 from electron/more-tests
test: More test, more minor refactoring
2019-01-02 22:47:52 +08:00
Felix Rieseberg 4212284fc4 test: Update Electron mock 2019-01-02 21:54:46 +08:00
Felix Rieseberg 8b35ff8f95 test: Add octokit spec 2019-01-02 21:54:39 +08:00
Felix Rieseberg 4d00ee9fd4 test: Add files spec 2019-01-02 21:54:27 +08:00
Felix Rieseberg 590db5304d test: Cover sorted map better 2019-01-02 21:54:18 +08:00
Felix Rieseberg e519ce2f13 test: Add highlight spec 2019-01-02 21:54:09 +08:00
Felix Rieseberg 8221920fab test: Add main spec 2019-01-02 21:53:48 +08:00
Felix Rieseberg 5de7ed7d9d test: Move out first-run, add tests 2019-01-02 21:53:36 +08:00
Felix Rieseberg a1586e864a Merge pull request #141 from electron/tests-and-security
test: Increase test coverage, make some code safer
2019-01-02 09:31:36 +08:00
Felix Rieseberg 60745ff8bb test: Add fancy-import test 2018-12-30 19:09:28 +01:00
Felix Rieseberg 4ac20aa5c2 test: Add highlight-text test 2018-12-30 19:09:20 +01:00
Felix Rieseberg 48faec9741 test: Add tests for firstRun, use outputFile 2018-12-30 18:51:08 +01:00
Felix Rieseberg c0f4e95a67 test: Add some version tests 2018-12-30 18:39:39 +01:00
Felix Rieseberg d5c8c8bd96 test: Add some editors tests 2018-12-30 18:18:39 +01:00
Felix Rieseberg 80ff396879 test: Add dialog-warning tests 2018-12-30 17:34:35 +01:00
Felix Rieseberg bf42abc88d test: Update dialog-token tests 2018-12-30 17:11:49 +01:00
Felix Rieseberg eaa064ea8d test: Update dialog-add-version tests 2018-12-30 17:01:57 +01:00
Felix Rieseberg e804436669 test: Update commands-runner tests 2018-12-30 16:58:30 +01:00
Felix Rieseberg 08d07b34a4 chore: Safer commands-runner 2018-12-30 16:53:42 +01:00
Felix Rieseberg 74ba7db13c Merge pull request #140 from electron/fix-cert-file
ci: Properly find Windows codesign certificate
2018-12-24 18:06:42 +01:00
Felix Rieseberg 0fced3aefd ci: Resolve path correctly 2018-12-24 17:56:41 +01:00
Felix Rieseberg 13c9217f9f ci: Fix variable test 2018-12-24 17:52:31 +01:00
Felix Rieseberg 346742b242 ci: Properly find Windows codesign certificate 2018-12-24 17:21:15 +01:00
Felix Rieseberg aefe273516 Merge pull request #139 from electron/bump-041
chore: Bump version number
2018-12-24 16:20:59 +01:00
Felix Rieseberg 337d19c33a chore: Bump version number 2018-12-24 16:15:58 +01:00
Felix Rieseberg ebc6f91dea Merge pull request #138 from electron/fix-tour
fix: The Tour
2018-12-24 16:09:50 +01:00
Felix Rieseberg 25446aa9e4 chore: Update snapshots 2018-12-24 15:27:29 +01:00
Felix Rieseberg f2859c053b chore: Goodbye, dialog component 2018-12-24 14:39:56 +01:00
Felix Rieseberg 49cd192817 feat: Modernize and improve tour 2018-12-24 14:26:09 +01:00
Felix Rieseberg 9bdd09c6b5 fix: Tour selectors 2018-12-24 13:48:13 +01:00
Felix Rieseberg c3d36b29b0 feat: Modernize the tour buttons 2018-12-24 13:44:15 +01:00
Felix Rieseberg 1b69a2ff52 Merge pull request #137 from electron/ci-publish-win
ci: Allow AppVeyor to codesign
2018-12-24 12:19:18 +00:00
Felix Rieseberg 311497d080 ci: AppVeyor: Use Node 10 2018-12-24 13:01:13 +01:00
Felix Rieseberg 55b7739d36 ci: AppVeyor: Upload build artifacts, build ia32 2018-12-24 13:00:28 +01:00
Felix Rieseberg 0fda97eb2f ci: AppVeyor: Print build artifacts 2018-12-24 12:52:45 +01:00
Felix Rieseberg 879815fc02 ci: Allow AppVeyor to codesign 2018-12-24 12:39:33 +01:00
Felix Rieseberg c469c3e856 Merge pull request #136 from electron/fix-windows-tests
test: Fix Windows tests
2018-12-24 08:29:31 +00:00
Felix Rieseberg 1b6750e0c5 Merge pull request #135 from electron/ci-publish
ci: Allow Travis to create signed macOS builds
2018-12-24 08:23:41 +00:00
Felix Rieseberg f14bd5c041 test: Fix Windows tests 2018-12-24 09:22:15 +01:00
Felix Rieseberg 76115a3e9c fix: Little linter error 2018-12-24 09:13:43 +01:00
Felix Rieseberg 65f86e0177 Merge branch 'ci-publish' of https://github.com/electron/fiddle into ci-publish 2018-12-24 09:10:36 +01:00
Felix Rieseberg 18cacb1532 chore: Silence the import 2018-12-24 09:10:27 +01:00
Mark Leeandfelixrieseberg 6a924ac88b Update forge.config.js
Co-Authored-By: felixrieseberg <felix@felixrieseberg.com>
2018-12-24 07:56:55 +00:00
Felix Rieseberg d125af6775 chore: Update the CI config 2018-12-24 08:51:15 +01:00
Felix Rieseberg 1a9a0579a5 chore: Add intermediate macOS certificates 2018-12-24 07:21:30 +01:00
Felix Rieseberg acee131288 chore: Install publisher-github 2018-12-24 07:20:45 +01:00
Felix Rieseberg 66536a5260 Merge pull request #134 from electron/fix-data-dir
feat: Prune appData directories after runs
2018-12-24 05:27:42 +00:00
Shelley Vohr 7941a83109 chore: fix 8 low severity vulns 2018-12-23 10:26:57 -07:00
Felix Rieseberg b312b80b69 fix: Throw error in contributors.js 2018-12-23 18:26:22 +01:00
Shelley Vohr b3c3b73b7d feat: prompt users to move to application folder (#132) 2018-12-23 10:25:37 -07:00
Shelley Vohr 0a8e9cde1b chore: add codebytere to contributors 2018-12-23 10:21:55 -07:00
Felix Rieseberg ca3f48697d chore: Add some tests 2018-12-23 17:57:51 +01:00
Felix Rieseberg 067e5cd5e2 feat: Delete app data dir after run 2018-12-23 17:57:51 +01:00
Felix Rieseberg 7e16c8c1f2 chore: Move runner logic out of component 2018-12-23 17:57:51 +01:00
Felix Rieseberg e932aad47b Merge pull request #131 from electron/electron-311
feat: Update to Electron 3.0.11
2018-12-20 09:45:49 -08:00
Felix Rieseberg 82fb8290c3 Merge pull request #130 from electron/modern-add-version-dialog
feat: Modernize 'add local build' dialog
2018-12-20 09:38:29 -08:00
Felix Rieseberg 2eb8bb3cf5 infra: Update to Electron 3.0.11 2018-12-20 09:38:04 -08:00
Felix Rieseberg 3d6448030a feat: Modernize 'add local build' dialog 2018-12-20 09:28:50 -08:00
Felix Rieseberg 65855908d1 Merge pull request #128 from electron/fix-confusing-dialog
fix: Confusing "Fiddle unsaved" dialog
2018-12-20 09:11:08 -08:00
Felix Rieseberg 9e986e24e2 Merge pull request #129 from electron/bump-040
chore: Update version number
2018-12-20 08:57:38 -08:00
Felix Rieseberg 9abc358bd9 fix: Linter issues 2018-12-20 08:57:23 -08:00
Felix Rieseberg 7f7785c69c chore: Update version number 2018-12-19 17:17:40 -08:00
Felix Rieseberg f36f300feb feat: Improve exit dialog, too 2018-12-19 17:16:59 -08:00
Felix Rieseberg 2c49214a25 fix: Confusing unsaved dialog 2018-12-19 16:57:52 -08:00
Felix Rieseberg c7a8163990 Merge pull request #127 from electron/fix-show-me
fix: "Show me" casing issue on Windows
2018-12-19 11:03:03 -08:00
Felix Rieseberg 97995b0ec2 fix: Lowercase for all templates 2018-12-19 10:24:48 -08:00
Felix Rieseberg d2377dcc30 Merge pull request #126 from electron/feat-npm-releases
feat: Use npm registry to fetch releases
2018-12-18 14:39:41 -08:00
Felix Rieseberg ac1197faaa fix: Two more fixes 2018-12-18 13:59:43 -08:00
Felix Rieseberg 9fb9aa6c92 fix: Make linter happy 2018-12-18 13:44:53 -08:00
Felix Rieseberg 6c5e41a2f1 feat: Use npm to download releases 2018-12-18 12:32:13 -08:00
Felix Rieseberg 4b52c81101 chore: Update the built-in releases file 2018-12-18 12:31:47 -08:00
Felix Rieseberg 35f4f1293c infra: Have fetch-releases use npm 2018-12-18 12:31:47 -08:00
Felix Rieseberg 8840b1ef7f Merge pull request #125 from electron/forge-arch-squirrel
chore: automatically add arch to squirrel installer filename
2018-12-18 12:31:16 -08:00
Felix Rieseberg d516522af2 Merge pull request #124 from electron/feat-public-private
feat: Publish fiddles as public/private
2018-12-18 12:30:35 -08:00
Mark Lee 0d0a51a900 infra: automatically add arch to squirrel installer filename 2018-12-17 23:53:46 -08:00
Felix Rieseberg be3b1e4a5b feat: Publish fiddles as public/private 2018-12-17 16:42:55 -08:00
Felix Rieseberg 2acc7112b7 fix: gistId in address bar without url 2018-12-17 16:04:13 -08:00
Felix Rieseberg 407bf3caeb Merge pull request #120 from electron/redesign
feat: Minor redesign, new component library
2018-12-17 15:54:04 -08:00
Felix Rieseberg 49123116d5 fix: Incorrect "arch" reference 2018-12-17 14:08:57 -08:00
Felix Rieseberg 9f6bc2f26f fix: Remove FontAwesome 2018-12-17 09:04:20 -08:00
Felix Rieseberg 5585e2d5d0 feat: Modernize the Token Dialog 2018-12-13 16:37:51 -08:00
Felix Rieseberg 4235969526 fix: forge.config.js 2018-12-13 16:20:25 -08:00
Felix Rieseberg 659d41f1c8 feat: Modernize Electron settings, credits 2018-12-12 18:23:59 -08:00
Felix Rieseberg 2549992782 feat: Modernize settings menu items 2018-12-12 18:23:59 -08:00
Felix Rieseberg b7314b83ee feat: Modernize the GitHub settings 2018-12-12 18:23:59 -08:00
Felix Rieseberg 39c2a9164a feat: Modernize appearance settings 2018-12-12 18:23:59 -08:00
Felix Rieseberg 1a9dc1fbf7 chore: Reorganize some more files 2018-12-12 18:23:59 -08:00
Felix Rieseberg 0eb01c4692 feat: Modernize the publish button 2018-12-12 18:23:59 -08:00
Felix Rieseberg 96667a3b04 chore: Rename publish-button to commands-publish-button 2018-12-12 18:23:59 -08:00
Felix Rieseberg 4365513f57 feat: Modernize address bar 2018-12-12 18:23:59 -08:00
Felix Rieseberg 913b37c285 chore: Rename address-bar 2018-12-12 18:23:59 -08:00
Felix Rieseberg 66c55d39c0 fix: Correctly display colors 2018-12-12 18:23:59 -08:00
Felix Rieseberg 0f3a3aca72 chore: Reorganize styles 2018-12-12 18:23:59 -08:00
Felix Rieseberg 3fc974a758 feat: Modernize the run button 2018-12-12 18:23:59 -08:00
Felix Rieseberg 72b805059c feat: Update version selector 2018-12-12 18:23:59 -08:00
Felix Rieseberg 291882ac5c infra: Simplify and improve parcel build 2018-12-12 18:23:59 -08:00
Felix Rieseberg 3c05cc8ec7 Merge pull request #119 from electron/update-windows-installer-icon
chore: update windows installer icon
2018-12-12 15:30:13 -08:00
Mark Lee 75d2f9ff72 🎨 update windows installer icon 2018-12-12 13:30:35 -08:00
Felix Rieseberg 0119f0ce69 Merge pull request #118 from electron/new-icon
docs: New icon
2018-12-12 13:22:48 -08:00
Mark Lee 8ed5ea94b5 Add SVG to .deb file 2018-12-11 23:53:04 -08:00
simurai deaac4e15c docs: Add icon as SVG 2018-12-12 12:47:53 +09:00
simurai 48e58c095d docs: Use transparent background for README icon 2018-12-11 16:48:07 +09:00
simurai 28f0eca429 docs: Replace loading gif 2018-12-11 12:02:02 +09:00
simurai 529906e1a9 docs: Replace icons 2018-12-11 09:20:15 +09:00
simurai 40c9aaeb7a docs: Add icon to README 2018-12-10 16:36:03 +09:00
Felix Rieseberg 15924c7741 fix: Make the linter happy 2018-11-27 15:47:56 -08:00
Felix Rieseberg c62041a000 Merge pull request #115 from electron/updates-2
chore: Updates for everyone
2018-11-27 15:46:50 -08:00
Felix Rieseberg ff3e931d14 fix: Apply lint fixes 2018-11-27 13:40:58 -08:00
Felix Rieseberg 7cc16b6fab infra: Update to electron-forge v6 beta 30 2018-11-27 13:40:08 -08:00
Felix Rieseberg 45e8e311da Merge pull request #111 from electron/tour-buttons
fix: friendlier button text for intro tour
2018-11-27 13:08:39 -08:00
Felix Rieseberg b09e792583 chore: Fix type errors in npm 2018-11-27 13:07:57 -08:00
Felix Rieseberg cdb862442c infra: Use library mode in fontawesome 2018-11-27 13:03:19 -08:00
Felix Rieseberg 1e1566dbdb infra: Update TypeScript 2018-11-27 13:03:04 -08:00
Felix Rieseberg e571fcca4f fix: style and logic in npm.ts 2018-11-27 13:02:50 -08:00
Felix Rieseberg e61e49987e infra: Update node-abi, node-fetch 2018-11-27 11:47:45 -08:00
Felix Rieseberg 133411c150 infra: Update mobx 2018-11-27 11:46:48 -08:00
Felix Rieseberg db8c7c32ab infra: Update react, semver 2018-11-27 11:44:59 -08:00
Felix Rieseberg 003e27f57e infra: Update monaco-editor 2018-11-27 11:41:57 -08:00
Felix Rieseberg 72d717bd48 infra: Update Electron to 3.0.10 2018-11-26 15:11:34 -08:00
Felix Rieseberg 675500fe25 infra: Update fontawesome 2018-11-26 12:38:23 -08:00
Felix Rieseberg fbe2311d53 infra: Update electron-forge to lastest beta 2018-11-26 12:37:09 -08:00
Felix Rieseberg ef42b1affe tests: Fix tests 2018-11-23 11:35:53 -08:00
Felix Rieseberg 2adde7d9ce Merge pull request #114 from ada-lovecraft/master
fix: erroneous require behavior
2018-11-23 11:28:54 -08:00
Ada Lovecraft 5fa0ddcc73 cleaned up npm module searching and added inline docs 2018-11-21 12:22:46 -06:00
Ada Lovecraft 5d501f0827 fixed npm module loading 2018-11-21 00:33:35 -06:00
Jeremy Apthorp d738936952 friendlier button text for intro tour
In general I like it when buttons are labeled with what's going to happen when I click on them
2018-11-09 13:33:01 -08:00
Shelley Vohr 57ce8b0b79 chore: remove unused requires in main (#109) 2018-10-30 16:55:08 -07:00
Felix Rieseberg 46f4efb4b4 Merge pull request #106 from electron/minor-fixups
feat: Add key property for buttons, update electron and typescript
2018-10-11 16:35:51 -04:00
HashimotoYT 10a696a9d7 Update test snapshot 2018-10-11 23:25:38 +03:00
HashimotoYT 585c0e1183 Update Electron, add myself to contributors. 2018-10-11 21:40:16 +03:00
HashimotoYT 946d32fdd0 Update TypeScript and Electron 2018-10-11 02:19:17 +03:00
HashimotoYT f09363ec26 Add key prop for buttons in token dialog 2018-10-11 02:11:40 +03:00
Felix Rieseberg 1a6876497a Merge pull request #104 from electron/hashi/gist-error-message
feat: provide error message for Token dialog
2018-10-08 16:49:56 -07:00
HashimotoYT 6bc04f5d2a Trying revert templates 2018-10-09 02:16:46 +03:00
HashimotoYT 9f7bf9d299 Provide error message for token dialog 2018-10-08 01:33:09 +03:00
Felix Rieseberg 3b7873917f Merge pull request #103 from electron/local-versions
feat: Add support for local Electron builds (with versions)
2018-10-05 19:17:04 -07:00
Felix Rieseberg 4616f12d6c 👷 Fix snapshot issues 2018-10-05 19:02:57 -07:00
Felix Rieseberg 63f37c9553 👷 Add a few tests 2018-10-05 18:56:22 -07:00
Felix Rieseberg 09edfa16b0 👷 Update snapshots 2018-10-05 18:56:22 -07:00
Felix Rieseberg da3a607bc1 🔧 Pretty version chooser 2018-10-05 18:56:22 -07:00
Felix Rieseberg 5fcc34b035 🔧 Parse the version 2018-10-05 18:56:22 -07:00
Felix Rieseberg dfed297226 👷 Fix existing tests 2018-10-05 18:56:22 -07:00
Felix Rieseberg 7cb2c4d188 🔧 Run local versions 2018-10-05 18:56:22 -07:00
Felix Rieseberg f0215d8c90 🔧 Add local version dialog 2018-10-05 18:56:21 -07:00
Felix Rieseberg ffdb57e2f3 🔧 More of it all 2018-10-05 18:56:11 -07:00
Felix Rieseberg e5dd6ffb4e 🎨 Use the correct delete icon 2018-09-28 16:11:32 -07:00
Felix Rieseberg 1083b6c2de 🔧 Cleanup 2018-09-28 13:45:46 -07:00
Felix Rieseberg 73b6cb0cb2 🔧 Get all versions during refresh 2018-09-28 13:14:53 -07:00
Felix Rieseberg 3e5914b192 🔧 Basic state support for local versions 2018-09-28 13:11:30 -07:00
Felix Rieseberg fe81d5c14c Merge pull request #102 from electron/update-dependencies
chore: Update all the dependencies
2018-09-27 13:16:49 -07:00
Felix Rieseberg c85536a8b9 🔧 Implement deprecations 2018-09-27 13:05:03 -07:00
Felix Rieseberg 8d90dbed09 🔧 Update tests 2018-09-27 13:01:44 -07:00
Felix Rieseberg b918c13c72 🔧 Fix standardJs lint issues 2018-09-27 11:43:47 -07:00
Felix Rieseberg 570bab9c29 🔧 Refactor and fix code lint issues 2018-09-27 11:42:50 -07:00
Felix Rieseberg f0f7ed22ee 📦 Update stylelint and standard 2018-09-27 10:40:43 -07:00
Felix Rieseberg a62c1550a1 📦 Update TypeScript 2018-09-27 10:39:39 -07:00
Felix Rieseberg 754473e10a 📦 Update to Electron 3.0.1 2018-09-27 10:32:21 -07:00
Felix Rieseberg 732f81cd33 📦 Update namor 2018-09-27 10:20:01 -07:00
Felix Rieseberg 47e5182117 📦 Update Octokit 2018-09-27 10:18:55 -07:00
Felix Rieseberg 92c831cc7b 📦 Update FontAwesome 2018-09-27 10:18:04 -07:00
Felix Rieseberg 8ffb215797 📦 Bump React 2018-09-27 10:17:30 -07:00
Felix Rieseberg 616264f017 📦 Bump mobx 2018-09-27 10:16:21 -07:00
Felix Rieseberg ee6e474b04 📦 Bump the version number 2018-09-27 10:15:46 -07:00
Felix Rieseberg ee8fa678f9 Merge pull request #101 from electron/fix-download-link
fix: don't pin download link to 0.1 tag
2018-09-27 09:44:25 -07:00
Felix Rieseberg e605ef399d 📝 Point to latest 2018-09-27 09:44:18 -07:00
Charles Kerr e653cb5c0f fix: don't pin download link to 0.1 tag 2018-09-26 15:29:16 -05:00
Felix Rieseberg 44df77b7e8 Merge pull request #94 from BeniCheni/gist-link-input
fix: Adjust gist link address bar
2018-09-25 07:12:07 -07:00
Felix Rieseberg 99db07e000 👷 And again 2018-09-25 07:04:38 -07:00
Felix Rieseberg 0f7498e5ea 👷 Fix them again 2018-09-25 06:52:46 -07:00
Felix Rieseberg b30a3cb493 👷 Update snapshots 2018-09-25 06:45:17 -07:00
Felix Rieseberg 6686f8f1b3 🔧 Fix the pattern validation 2018-09-25 06:34:38 -07:00
Felix Rieseberg 5db586b34d 🎨 Fix the input field style 2018-09-25 06:34:15 -07:00
Felix Rieseberg 076c3dedaa 🔧 Correctly expand input field 2018-09-25 06:17:48 -07:00
Felix Rieseberg 2bf245bbb9 Merge branch 'gist-link-input' of https://github.com/BeniCheni/fiddle into BeniCheni-gist-link-input 2018-09-25 06:04:13 -07:00
Felix Rieseberg 6445d82dfa Merge pull request #95 from nctl144/soft_wrap
feat: enable options for the text editor
2018-09-25 06:03:21 -07:00
Benjamin Chen bbbbea8a27 🔧 Update gist link address bar per PR comments
Refs: https://github.com/electron/fiddle/pull/94#issuecomment-419883846
2018-09-24 23:07:48 -04:00
Mark Lee 7f4e6c70d9 🔧 don't hang on window close when run via npm start
Fixed via Electron Forge v6.0.0-beta.28

See: https://github.com/electron-userland/electron-forge/pull/567
2018-09-24 23:07:48 -04:00
nctl144 ebbd98b1dd fix equal syntax 2018-09-22 14:27:19 -04:00
nctl144 712707026c fix the var type 2018-09-22 13:12:45 -04:00
nctl144 595ad0e5ab enable minimap toggle 2018-09-21 16:51:32 -04:00
nctl144 4c09f69435 fix the syntax error 2018-09-21 16:25:59 -04:00
nctl144 deb6bd6323 delete debug log 2018-09-21 16:06:54 -04:00
nctl144 db7b8861b5 enable toggle soft wrap 2018-09-16 17:50:51 -04:00
nctl144 ca5600d521 test new methods 2018-09-16 17:17:38 -04:00
nctl144 619d48bfe3 get the value from the json file 2018-09-12 00:07:51 -04:00
nctl144 ab7dff11c9 fix the value in the json file 2018-09-12 00:07:17 -04:00
nctl144 877a2ec434 register events 2018-09-11 23:55:22 -04:00
nctl144 7806bb47c8 create json file that allows loading editor values 2018-09-11 15:42:03 -04:00
Felix Rieseberg 25f73e5390 Merge pull request #97 from electron/fix-forge-start-exit
fix: don't hang on window close when run via npm start
2018-09-11 11:08:24 +02:00
Mark Lee 9eeecc94d5 🔧 don't hang on window close when run via npm start
Fixed via Electron Forge v6.0.0-beta.28

See: https://github.com/electron-userland/electron-forge/pull/567
2018-09-10 07:55:34 -07:00
nctl144 bcd37ff67c init the button for the soft wrap 2018-09-06 15:49:16 -04:00
Benjamin Chen 6099c7b1ea 🔧 Update address bar's left padding style & test 2018-09-05 22:39:52 -04:00
Benjamin Chen 237ce59100 🔧 Remove "placehold" from Gist Link address bar 2018-09-05 01:04:53 -04:00
Benjamin Chen 0289a92a06 🔧 Fix bug for Gist Link address bar 2018-09-05 00:55:01 -04:00
Felix Rieseberg 86fb981c98 🔧 Add windows certificate info 2018-08-29 15:53:29 -07:00
Felix Rieseberg 3d7cd9eeba 🔧 Force close 2018-08-29 15:24:46 -07:00
Felix Rieseberg 066da6433e Merge pull request #81 from electron/road-to-020
chore: Update dependencies, update version number
2018-08-29 09:34:44 -07:00
Felix Rieseberg b83378df5a 👷 Fix tests 2018-08-28 18:38:02 -07:00
Felix Rieseberg 5aaf46beb9 📦 Update TypeScript & friends 2018-08-28 18:30:37 -07:00
Felix Rieseberg 066195ed39 📦 Update React types 2018-08-28 18:29:53 -07:00
Felix Rieseberg 96ea7bfe61 🔧 Fix isFocused for editor 2018-08-28 18:27:16 -07:00
Felix Rieseberg 0e68605a05 📦 Update Parcel 2018-08-28 18:26:47 -07:00
Felix Rieseberg 7a5d84908f 🔧 Harden version-chooser 2018-08-28 18:13:44 -07:00
Felix Rieseberg e3ff84f14e 🔧 Fix: Don't save 0 known versions 2018-08-28 18:02:50 -07:00
Felix Rieseberg 37d6f63b33 🔧 Fix: Always display cut, copy, paste 2018-08-28 17:55:13 -07:00
Felix Rieseberg 8867679f3a Merge pull request #92 from electron/margin-error
fix: Correct padding error
2018-08-28 17:49:42 -07:00
Felix Rieseberg 12d9892be5 Merge pull request #93 from electron/unchanged-error-guard
fix: Prevent error in isContentUnchanged
2018-08-28 17:49:32 -07:00
Felix Rieseberg 28ccff3254 📦 Update enzyme, less, jest 2018-08-28 17:48:56 -07:00
Felix Rieseberg e8ab965579 📦 Update Electron 2018-08-28 17:47:52 -07:00
Felix Rieseberg e0d5ceacdf 📦 Update mobx 2018-08-28 17:45:54 -07:00
Felix Rieseberg d62a2a2c78 📦 Update fs-extra, electron-download 2018-08-28 17:43:51 -07:00
Felix Rieseberg e5d2bfa7a3 📦 Update React, mobx, semver 2018-08-28 17:38:38 -07:00
Felix Rieseberg 0e05a34efa 🔧 Fix missing removeItem mock 2018-08-28 17:38:38 -07:00
Felix Rieseberg 1f4f489947 📦 Update version number to 0.2.0 2018-08-28 17:38:38 -07:00
Felix Rieseberg 9cab776159 🔧 Fix last bugs 2018-08-28 17:38:38 -07:00
Felix Rieseberg 26e3f09b95 🔧 Prevent error in isContentUnchanged 2018-08-28 17:36:45 -07:00
Felix Rieseberg 3c9f06909b 🔧 Fix margin error 2018-08-28 17:32:22 -07:00
Felix Rieseberg 779f273339 Merge pull request #89 from aaronabramov/enzyme-to-json
test: use enzyme-to-json and fix tests
2018-08-28 12:56:47 -07:00
Felix Rieseberg 1cdfb0f031 Merge pull request #84 from BeniCheni/adjust-mosaic-styles
fix: Update mosaic less to improve tooltip styles
2018-08-28 12:55:00 -07:00
Aaron Abramov 6103db3a80 use enzyme-to-json 2018-08-24 15:53:16 -07:00
Beni von Cheni 8b63134324 📚 Add "benicheni" to contributor list per prev help on #78 (#83) 2018-08-23 10:17:19 -05:00
Benjamin Chen 60e58dbd5a 🎨 Update mosaic less to improve tooltip styles 2018-08-22 01:21:05 -04:00
Felix Rieseberg 38b7b08691 Merge pull request #82 from nctl144/credit
chore: Add myself to the contributor list
2018-08-21 20:03:58 -07:00
nctl144 5acdcc4ab2 add myself to the contributor list 2018-08-21 22:47:54 -04:00
Felix Rieseberg 8dd587ac7e Merge pull request #80 from electron/flexible-quick-start
feat: Make quick start flexible
2018-08-21 19:00:07 -07:00
Felix Rieseberg aba46cd666 🔧 Do it on boot, too 2018-08-21 18:04:09 -07:00
Felix Rieseberg 3286852006 🔧 Make quick start flexible 2018-08-21 18:00:24 -07:00
Felix Rieseberg 2682a3f67c Merge pull request #79 from electron/old-versions
feat: Allow old versions, enable configurable list
2018-08-21 13:04:22 -07:00
Felix Rieseberg 6e7fb45334 👷 One more test fix 2018-08-21 12:56:19 -07:00
Felix Rieseberg 0ef82b6ad6 🔧 Linter 2018-08-21 12:37:45 -07:00
Felix Rieseberg 41c6dd3d44 👷 Add a few tests 2018-08-21 12:30:42 -07:00
Felix Rieseberg c6f90331b9 👷 Fix existing tests 2018-08-21 12:11:15 -07:00
Felix Rieseberg d7b00c4166 Merge pull request #77 from nctl144/sp_electron18
fix: Support Electron <1.8.x
2018-08-21 08:46:40 -07:00
Felix Rieseberg 3fef83356d Merge pull request #78 from BeniCheni/adjust-mosaic-window-styles
fix: Adjust .mosaic-window-body styles
2018-08-21 08:45:52 -07:00
Benjamin Chen 34be3369f3 🐛 Adjust .mosaic-window-body styles 2018-08-20 22:25:21 -04:00
nctl144 5c04d74ebc replace loadFile with loadURL 2018-08-20 15:57:35 -04:00
Felix Rieseberg 29ac8334fe 🔧 Configurable version options 2018-08-17 18:45:35 -07:00
Felix Rieseberg 604251260d 🔧 Allow for multiple pages 2018-08-17 10:53:20 -07:00
Gökay Gürcan 7015e49725 🔧 📝 Broken link (#73) 2018-08-14 06:41:56 -07:00
Felix Rieseberg d3a19c9b3c Merge pull request #71 from electron/open-folder-on-save
fix: Do not use "showItemInFolder" on save
2018-08-13 17:57:37 -07:00
Felix Rieseberg 6958192096 Merge pull request #72 from electron/fix-path-linux
fix: Path on Linux, too
2018-08-13 16:13:56 -07:00
Felix Rieseberg 100be9548e Merge pull request #70 from electron/themes
feat: Theme support
2018-08-13 16:13:42 -07:00
Felix Rieseberg bff1e23be3 🔧 Fix path on Linux, too 2018-08-13 08:34:15 -07:00
Felix Rieseberg 8e6ddd59fb 🔬 Update tests 2018-08-13 08:33:31 -07:00
Felix Rieseberg 419b5f57a0 🔧 Fix "showItemInFolder" use on save 2018-08-13 08:29:48 -07:00
Felix Rieseberg 27858cac6a 🔧 Update GitHub Settings header 2018-08-13 08:25:44 -07:00
Felix Rieseberg ac7221b117 🔬 Test create theme button 2018-08-13 08:24:30 -07:00
Felix Rieseberg 31c898f082 🔧 Create new theme from current 2018-08-13 08:04:17 -07:00
Felix Rieseberg 1bc381571c 🔬 Test CSS string methods 2018-08-13 07:04:58 -07:00
Felix Rieseberg 33902dbe01 🔧 Cleaner methods 2018-08-13 06:51:50 -07:00
Felix Rieseberg 2285b14184 🔧 Fix linter errors 2018-08-12 22:44:43 -07:00
Felix Rieseberg b67654769f 🔬 Add tests for settings-general 2018-08-12 22:34:49 -07:00
Felix Rieseberg 8cc6f766a5 🔬 Fix tests, add themes-spec 2018-08-12 21:58:53 -07:00
Felix Rieseberg c21e398c89 🎨 Improve themed console look 2018-08-12 20:53:31 -07:00
Felix Rieseberg 8019951e8c 🎨 Fix the Electron buttons 2018-08-12 20:37:07 -07:00
Felix Rieseberg 707ee2192f 🔧 Add theme settings and methods 2018-08-12 20:31:51 -07:00
Felix Rieseberg 2a4e59461e 🎨 Use nothing but variables in styles 2018-08-12 20:30:35 -07:00
Felix Rieseberg 22440298d7 🔧 Allow loading from disk 2018-08-12 18:00:39 -07:00
Felix Rieseberg 37168a99ee 🔧 Basic theme support 2018-08-12 17:48:19 -07:00
Charles Kerr 40254126d0 Merge pull request #65 from regularfry/patch-1
Punctuation fix
2018-08-11 10:25:09 -05:00
Alex Young 492893b71a Punctuation fix
"Let's" would mean "let us", or "of the let".  "Lets" is "allows", which is what's needed here.
2018-08-11 10:43:32 +01:00
Felix Rieseberg a1c91727ae Merge pull request #64 from cmpscabral/master
Add missing script tag for renderer process
2018-08-10 14:34:49 -07:00
Carlos 634d0ca734 Add missing script tag for renderer process 2018-08-10 20:43:24 +01:00
Felix Rieseberg 1557841c81 📝 Add a download button 2018-08-10 08:05:17 -07:00
Felix Rieseberg ff3fbac7ed 🔧 Fix "New Fiddle" 2018-08-10 07:45:17 -07:00
Felix Rieseberg 82f83acba4 🔧 Fix the menu shortcut 2018-08-09 18:37:35 -07:00
Felix Rieseberg f957e0c53a 🔧 Last minute npm fix 2018-08-09 18:34:26 -07:00
Felix Rieseberg bd1915a0f8 🔧 Case-sensitive folder names 2018-08-09 16:49:56 -07:00
Felix Rieseberg 01413c8830 🔧 Update Electron release 2018-08-09 16:40:22 -07:00
Felix Rieseberg 62002debd4 🔧 Fix typos 2018-08-09 16:27:07 -07:00
Felix Rieseberg 7fc1008121 Merge pull request #58 from electron/icons
feat: Update icons
2018-08-09 14:33:02 -07:00
Felix Rieseberg aaf183614f Merge pull request #59 from electron/update-electron
infra: Upgrade to Electron 2.0.7
2018-08-09 13:35:13 -07:00
Felix Rieseberg 4a2a73b780 🔧 Update path (take 2) 2018-08-09 13:23:41 -07:00
Felix Rieseberg a5985e8dde 🔧 Update path (take 1) 2018-08-09 13:22:57 -07:00
Felix Rieseberg b5bf652df0 🎨 Smaller ico file 2018-08-09 13:13:03 -07:00
Felix Rieseberg 79cdad1291 📦 Electron 2.0.7 2018-08-09 13:05:12 -07:00
Felix Rieseberg 35b7b8994f Merge pull request #57 from electron/security-basics
fix: Some sane security basics
2018-08-09 13:02:21 -07:00
Felix Rieseberg 1ca25fe515 🔬 Fix tests 2018-08-09 12:53:04 -07:00
Felix Rieseberg 82976cb269 🎨 Update icons 2018-08-09 12:46:40 -07:00
Felix Rieseberg 6487db8207 🔧 Some sane security basics 2018-08-09 07:08:59 -07:00
Felix Rieseberg 325cb3416a Merge pull request #56 from electron/unsaved-handling
feat: Handle saved/unsaved state
2018-08-09 07:04:23 -07:00
Felix Rieseberg 73ea0873f8 📦 0.1.0 2018-08-08 20:31:14 -07:00
Felix Rieseberg 987d05dd0f 🔧 Handle saved/unsaved state 2018-08-08 20:29:05 -07:00
Felix Rieseberg 61e8524996 Merge pull request #54 from electron/multi-window
feat: Multi window support
2018-08-08 20:02:08 -07:00
Felix Rieseberg 82b0fea020 Merge pull request #55 from electron/fix-fiddle
fix: Install beta.22 of Fiddle
2018-08-08 20:01:58 -07:00
Felix Rieseberg caff29dc39 🔧 Handle missing npm 2018-08-08 19:49:48 -07:00
Felix Rieseberg de1a908a6e 🔧 Install the beta.22 of forge 2018-08-08 19:44:02 -07:00
Felix Rieseberg 766cf9100a 🔬 Fix tests 2018-08-08 19:42:06 -07:00
Felix Rieseberg 27dc99e7cb 🔧 Create new windows 2018-08-08 19:38:50 -07:00
Felix Rieseberg d711082c67 🔧 Allow new window creation 2018-08-08 19:36:15 -07:00
Felix Rieseberg 7ac567e522 📝 Update Readme 2018-08-08 19:26:59 -07:00
Felix Rieseberg b074071333 Merge pull request #52 from electron/teach-me
feat: Teach me
2018-08-08 18:55:25 -07:00
Felix Rieseberg 82716bf02c 🔧 Cleanup 2018-08-08 18:42:49 -07:00
Felix Rieseberg 11d062e6e0 🏫 Template for webFrame 2018-08-08 18:41:49 -07:00
Felix Rieseberg 05ca117f02 🏫 Template for webContents 2018-08-08 18:34:19 -07:00
Felix Rieseberg 05e2785aa4 🏫 Template for Tray 2018-08-08 18:34:08 -07:00
Felix Rieseberg c2bc958504 🏫 Template for systemPreferences 2018-08-08 18:19:22 -07:00
Felix Rieseberg f2829e851c 🏫 Template for TouchBar 2018-08-08 18:17:18 -07:00
Felix Rieseberg b3d8971a1a 🏫 Template for shell 2018-08-08 18:09:18 -07:00
Felix Rieseberg b3c39f1546 🔧 Fix various errors 2018-08-08 18:09:12 -07:00
Felix Rieseberg a3ab1405a3 🔧 Clean old tmp folders 2018-08-08 18:04:05 -07:00
Felix Rieseberg 56632c94a0 🔧 Uppercase names 2018-08-08 17:53:48 -07:00
Felix Rieseberg 431b3d5bbc 🏫 Template for screen 2018-08-08 17:53:40 -07:00
Felix Rieseberg b4e1740294 🏫 Template for session 2018-08-08 17:53:27 -07:00
Felix Rieseberg 0d39c35081 🔧 Simplify HTML templates 2018-08-08 17:45:03 -07:00
Felix Rieseberg 685637e6c9 🏫 Template for powerMonitor 2018-08-08 17:44:53 -07:00
Felix Rieseberg 1b7f913bcf 🏫 Template for powerSaveBlocker 2018-08-08 17:44:44 -07:00
Felix Rieseberg 5b0d17c88a 🏫 Template for remote 2018-08-08 17:44:36 -07:00
Felix Rieseberg accf71da44 🏫 Template for net 2018-08-08 17:44:29 -07:00
Felix Rieseberg b2ff94744a 🏫 Template for Notification 2018-08-08 17:44:22 -07:00
Felix Rieseberg 58c656c2f3 🏫 Template for nativeImage 2018-08-08 17:11:39 -07:00
Felix Rieseberg 059dff3561 🏫 Template for Menu 2018-08-08 17:11:27 -07:00
Felix Rieseberg 32c4b6c804 🏫 Template for ipcRenderer, ipcMain 2018-08-08 16:45:32 -07:00
Felix Rieseberg 8b8197d3c8 🏫 Template for inAppPurchase 2018-08-08 16:45:17 -07:00
Felix Rieseberg dfd5afd115 🏫 Accelerator example is now the globalShortcut example 2018-08-08 16:45:01 -07:00
Felix Rieseberg 0336a4292e 🔧 Fix desktopCapturer template 2018-08-08 16:25:45 -07:00
Felix Rieseberg c39b84da3e 🔧 Fix linter errors 2018-08-08 09:05:56 -07:00
Felix Rieseberg 4c779b6033 🔧 Add standard linting to templates 2018-08-08 08:45:32 -07:00
Felix Rieseberg 2ebb46a988 🏫 Template for desktopCapturer 2018-08-07 19:23:28 -07:00
Felix Rieseberg 3413e1cb9f 🏫 Update various templates 2018-08-07 19:23:19 -07:00
Felix Rieseberg b1808ef8e6 🏫 Template for Cookies 2018-08-07 19:23:02 -07:00
Felix Rieseberg 558431a85c 🏫 Template for BrowserWindow 2018-08-07 19:22:47 -07:00
Felix Rieseberg 3edbc019c6 🏫 Template for dialog 2018-08-07 19:22:34 -07:00
Felix Rieseberg 06af8ba35f 🏫 Template for crashReporter 2018-08-07 19:22:27 -07:00
Felix Rieseberg 0aed40af5c 🏫 Template for Debugger 2018-08-07 19:22:19 -07:00
Felix Rieseberg bec4e2fd86 🏫 Template for contentTracing 2018-08-07 19:22:13 -07:00
Felix Rieseberg 5cd5881d35 🏫 Template for BrowserView 2018-08-07 19:22:03 -07:00
Felix Rieseberg fc3a7b2960 🏫 Template for clipboard 2018-08-07 19:21:51 -07:00
Felix Rieseberg 3f102b8ee7 Merge pull request #51 from electron/fix-dialog
fix: Dialog position on Linux and Windows
2018-08-07 17:06:14 -07:00
Felix Rieseberg 46450ee768 👷 Fix tests on Linux 2018-08-07 14:43:33 -07:00
Felix Rieseberg 33f9f9c1c3 🔧 More templates 2018-08-06 20:55:05 -07:00
Felix Rieseberg b731ae710c 🔧 A first batch of templates 2018-08-06 20:52:23 -07:00
Felix Rieseberg c486b0ee78 🔬 Add some tests 2018-08-06 20:35:52 -07:00
Felix Rieseberg 9e7dd4dc06 🔧 Add template support 2018-08-06 20:35:22 -07:00
Felix Rieseberg 99a37fbd82 🔧 Fix dialog position on Linux and Windows 2018-08-06 19:32:28 -07:00
Felix Rieseberg e27f7f29c1 Merge pull request #49 from electron/no-npm
feat: Handle missing npm
2018-08-06 19:20:29 -07:00
Felix Rieseberg 0b50e952ac Merge pull request #50 from electron/save-version
feat: Remember last selected version
2018-08-06 19:20:20 -07:00
Felix Rieseberg 58b252f7f2 🔧 Remember last selected version 2018-08-06 19:07:14 -07:00
Felix Rieseberg 5dffe5fce8 Merge branch 'master' into no-npm 2018-08-06 19:04:09 -07:00
Felix Rieseberg 2b6e4ee907 🔧 Handle missing npm better 2018-08-06 19:01:22 -07:00
Felix Rieseberg 9d85ae36d5 🔧 Check for npm 2018-08-05 22:33:41 -07:00
Felix Rieseberg 0f1ff6a70b Merge pull request #48 from electron/offline
feat: Support being offline better
2018-08-05 21:03:31 -07:00
Felix Rieseberg 1564284e30 🔬 Test runner/filemanager cleanup 2018-08-05 14:04:56 -07:00
Felix Rieseberg dd46a0fb7f 🔧 Remove temp directory on error 2018-08-05 14:04:43 -07:00
Felix Rieseberg 2536c0fc89 🔧 Allow contributors.js to work offline 2018-08-05 13:53:35 -07:00
Felix Rieseberg ff700845fb Merge pull request #47 from electron/more-unit-tests
More unit tests, fix "Save Fiddle"
2018-08-05 13:51:48 -07:00
Felix Rieseberg e74a2876b3 👷 Improve Travis test performance 2018-08-04 22:37:05 -07:00
Felix Rieseberg 440633ae3c :micrscope: Test App component 2018-08-04 15:38:39 -07:00
Felix Rieseberg 6b0ae32263 🔬 Test protocol 2018-08-04 13:45:46 -07:00
Felix Rieseberg 7d49f9076c 🤔 Let's cut "npm update" 2018-08-04 10:37:37 -07:00
Felix Rieseberg 7b2dbc5e1b 🔧 Goodbye, jest-localstorage-mock 2018-08-04 10:01:58 -07:00
Felix Rieseberg 331446a031 🔬 Test menu 2018-08-04 09:55:25 -07:00
Felix Rieseberg 62abe7e6e0 🔧 Set testURL 2018-08-04 08:55:02 -07:00
Felix Rieseberg c6ba5399a6 🔬 Test transforms 2018-08-03 20:12:55 -07:00
Felix Rieseberg b63302bb4b 🔧 Clean up all tests 2018-08-03 20:04:15 -07:00
Felix Rieseberg 9409b3280f 🔬 Test appState 2018-08-03 19:49:06 -07:00
Felix Rieseberg 5b3237d437 🔬 Test versions 2018-08-03 19:00:06 -07:00
Felix Rieseberg b606fa2bfe 🔬 Test themes 2018-08-03 18:25:19 -07:00
Felix Rieseberg 746ed2fd5d 🔬 Test npm 2018-08-03 18:23:47 -07:00
Felix Rieseberg 724fd39ba0 🔬 Test ipcRendererManager 2018-08-03 17:47:22 -07:00
Felix Rieseberg 65875235fe 🔬 Test FileManager component (ipc) 2018-08-03 17:42:49 -07:00
Felix Rieseberg 2d09369d6c 🔬 Test FileManager 2018-07-30 19:17:38 -07:00
Felix Rieseberg ee48344b9a Merge pull request #45 from electron/appveyor
test: Add AppVeyor, Readme badges
2018-07-30 18:40:09 -07:00
Felix Rieseberg bed5d7f739 Merge pull request #46 from electron/enforce-codestyle
test: Enfore a stricter code style
2018-07-30 18:39:56 -07:00
Felix Rieseberg efc2d6b3c4 🔧 Use npm ci 2018-07-30 18:20:10 -07:00
Felix Rieseberg aab01abff4 🔧 Apply linter changes 2018-07-30 18:07:46 -07:00
Felix Rieseberg 23aca61e4a 🔧 Clamp down on codestyle 2018-07-30 18:07:31 -07:00
Felix Rieseberg a057b2a26a 📝 Update Readme 2018-07-30 15:35:02 -07:00
Felix Rieseberg 8f754fb356 🔧 Add AppVeyor yaml file 2018-07-30 15:32:47 -07:00
Felix Rieseberg 528aba15e7 🔬 Add one more test 2018-07-30 15:29:43 -07:00
Felix Rieseberg 54dd7f8d3a Merge pull request #44 from electron/component-tests-2
test: More component tests (Editor, Dialogs, Header, Output)
2018-07-30 14:51:36 -07:00
Felix Rieseberg 6441c266b5 🔧 Update snapshots 2018-07-30 14:02:38 -07:00
Felix Rieseberg 66f19c3c6f 🔬 Increase component coverage 2018-07-30 13:28:27 -07:00
Felix Rieseberg ce7ba3cac1 🔧 Fix test output 2018-07-30 13:17:50 -07:00
Felix Rieseberg 9e53b09941 🔧 Enable "no-unused-expression" 2018-07-30 13:05:03 -07:00
Felix Rieseberg 6522890bcf 🔬 Test Runner component 2018-07-30 13:00:54 -07:00
Felix Rieseberg 8d9776da6a 🔬 Test WelcomeTour component 2018-07-30 10:55:54 -07:00
Felix Rieseberg 78905d9b6a 🔬 Test Tour component 2018-07-30 10:49:52 -07:00
Felix Rieseberg cfa0620aab 🔬 Test VersionChooser component 2018-07-30 10:26:27 -07:00
Felix Rieseberg 9e7cb2808e 🔬 Test TokenDialog component 2018-07-30 10:12:18 -07:00
Felix Rieseberg eb12f86725 🔬 Test Settings component 2018-07-30 09:24:28 -07:00
Felix Rieseberg d3651ef4ca 🔬 Test GitHubSettings component 2018-07-30 09:11:41 -07:00
Felix Rieseberg 6acce843c3 🔧 Update snapshots 2018-07-30 09:07:39 -07:00
Felix Rieseberg be6c1b0781 🔬 Test ElectronSettings component 2018-07-30 08:21:56 -07:00
Felix Rieseberg 241bec88b0 🔬 Test CreditsSettings component 2018-07-27 12:19:14 -07:00
Felix Rieseberg 48e5939d10 🔬 Test Publish Button component 2018-07-27 12:11:31 -07:00
Felix Rieseberg 2389e07781 🔬 Improve Output spec 2018-07-27 12:11:19 -07:00
Felix Rieseberg 56a4c8f641 🔧 Fix it harder 2018-07-27 11:54:24 -07:00
Felix Rieseberg c4a7929d82 🔧 Update the Output component, too 2018-07-27 08:39:29 -07:00
Felix Rieseberg 856b0cc437 🔧 Ugh, timezones. Output spec take II. 2018-07-27 08:39:10 -07:00
Felix Rieseberg 93613a421a 🔧 Update Output spec 2018-07-27 08:09:11 -07:00
Felix Rieseberg ea25ee4d78 🔬 Test Output component 2018-07-26 10:47:38 -07:00
Felix Rieseberg 20d3f351ff 🔬 Test Header component 2018-07-26 10:43:10 -07:00
Felix Rieseberg c64bb2c8ea 🔬 Test Editors component 2018-07-26 10:40:09 -07:00
Felix Rieseberg 5153921e43 🔬 Test editor 2018-07-26 10:25:14 -07:00
Felix Rieseberg aa763b839d 🔧 Test ergonomics 2018-07-26 10:25:10 -07:00
Felix Rieseberg fd1984d140 🔬 Test Dialogs component 2018-07-26 10:04:13 -07:00
Felix Rieseberg b63fe6bda2 🔬 Test Commands component 2018-07-26 09:54:32 -07:00
Felix Rieseberg a296945e0d 🔧 Enable noImplicitAny, noImplicitReturns 2018-07-26 09:47:08 -07:00
Felix Rieseberg 4938c0cd01 🔧 Consistent return 2018-07-26 09:46:33 -07:00
Felix Rieseberg cf30c9493e Merge pull request #42 from electron/component-tests
test: Test React components (a first set of them)
2018-07-26 09:45:36 -07:00
Felix Rieseberg 7a544cdd8e 🔧 Updating the snapshot, too 2018-07-26 09:13:02 -07:00
Felix Rieseberg 7e43acdd53 🔧 Specify platform in dialog tests 2018-07-25 23:23:00 -07:00
Felix Rieseberg 7ffe79c9e1 🔬 Test chrome-mac 2018-07-25 19:48:05 -07:00
Felix Rieseberg d68588aeb2 🔬 Test address bar 2018-07-25 19:45:27 -07:00
Felix Rieseberg 4b60316ebc 🔬 Test Dialog 2018-07-25 19:45:19 -07:00
Felix Rieseberg 4b5908b97d 🔧 Setup Enzyme 2018-07-25 19:45:02 -07:00
Felix Rieseberg 15f397f829 📦 Add Enzyme & friends 2018-07-25 19:44:53 -07:00
Felix Rieseberg e51f653ed9 Merge pull request #40 from electron/fix-settings-exit
fix: Settings toggle, context menu init, and a typo
2018-07-25 18:15:40 -07:00
Felix Rieseberg 8168ec9d26 👷 Fix test 2018-07-25 17:27:57 -07:00
Felix Rieseberg b11e6bd29e Merge pull request #41 from electron/save-as-dialog-titles
fix: save as dialog titles
2018-07-25 15:01:02 -07:00
Mark Lee 3ca0426994 fix: save as dialog titles
"Save as Forge Project" dialog title was incorrect.

"Save as" dialog title had `[Object BrowserWindow]` appended to it.
2018-07-24 23:50:20 -07:00
Felix Rieseberg 4106a63ee3 🔧 Fix context menu init 2018-07-24 08:53:34 -07:00
Felix Rieseberg ac4b5797fe 🔧 Fix settings toggle bug 2018-07-24 08:29:38 -07:00
Felix Rieseberg d66fecfb90 🔧 Fix welcome tour typo 2018-07-24 08:29:22 -07:00
Felix Rieseberg 50bbb895a9 Merge pull request #39 from electron/more-tests
test: More tests for binary, fetch-types, and content
2018-07-24 07:58:50 -07:00
Felix Rieseberg 970f06274a 🔧 Whoops, show the tasks menu 2018-07-23 22:33:40 -07:00
Felix Rieseberg 8ea6446dca 🔬 Test fetch-types 2018-07-23 22:28:19 -07:00
Felix Rieseberg 37e61a9cda 🔬 Test content 2018-07-23 21:38:16 -07:00
Felix Rieseberg 6defceb8d5 🔬 More binary tests 2018-07-23 21:35:13 -07:00
Felix Rieseberg 4e7349c48b 🔧 Fix this error 2018-07-23 21:32:20 -07:00
Felix Rieseberg 296396473c 🔬 Test binary manager 2018-07-23 21:31:23 -07:00
Felix Rieseberg a54a9d631e 🔧 Use custom import method 2018-07-23 21:31:13 -07:00
Felix Rieseberg 2e7c9ba7e4 Merge pull request #38 from electron/exec-fix
fix: exec `toString` test issue
2018-07-23 13:24:12 -07:00
Felix Rieseberg f58058a7da 🔧 Fix exec toString issue 2018-07-22 21:28:43 -07:00
Felix Rieseberg d3f3c047e9 Merge pull request #37 from electron/tests
infra: Add unit tests
2018-07-22 20:59:58 -07:00
Felix Rieseberg 4c1ec07684 👷 No, for real, surpress 2018-07-22 14:26:52 -07:00
Felix Rieseberg d4ccc0d17f 👷 Surpress console log/warn when in test 2018-07-22 14:13:14 -07:00
Felix Rieseberg edacde350f 🔧 Run test in Travis 2018-07-22 07:57:36 +08:00
Felix Rieseberg 48b49f48d0 🔧 Ignore yarn-error.log 2018-07-22 07:57:04 +08:00
Felix Rieseberg f21a4c72f6 🔬 Test binary (part I) 2018-07-22 07:56:00 +08:00
Felix Rieseberg e2bb88d4c5 🔬 Test windows 2018-07-22 07:18:25 +08:00
Felix Rieseberg 98d848a443 👷 Improve infrastructure 2018-07-22 07:02:27 +08:00
Felix Rieseberg e9a368adde 🔬 Test files 2018-07-22 06:56:11 +08:00
Felix Rieseberg 1194554a32 🔬 Test dialogs 2018-07-22 06:23:37 +08:00
Felix Rieseberg 816337f39c 🔬 Test context-menu 2018-07-22 06:13:45 +08:00
Felix Rieseberg 20a12db00d 🔬 Test content 2018-07-22 05:13:26 +08:00
Felix Rieseberg 8037a2e418 🔬 Test sorted-electron-map 2018-07-22 05:10:47 +08:00
Felix Rieseberg aed4c40956 🔬 Test sort-buttons 2018-07-22 05:04:35 +08:00
Felix Rieseberg d20d29c481 🔬 Test position-for-rect 2018-07-22 05:00:33 +08:00
Felix Rieseberg fcaa6b7a59 🔬 Test normalize-version 2018-07-22 04:46:14 +08:00
Felix Rieseberg 08dd132a4f 🔬 Test gist 2018-07-22 01:53:39 +08:00
Felix Rieseberg 92417e488c 🔬 Test get-username 2018-07-22 01:48:43 +08:00
Felix Rieseberg abc60ea21f 🔬 Test get-title 2018-07-22 01:45:30 +08:00
Felix Rieseberg 4a3a6d50f5 🔬 Test get-package 2018-07-22 01:39:27 +08:00
Felix Rieseberg a9d70f730c 🔬 Test focused-editor 2018-07-22 01:28:11 +08:00
Felix Rieseberg 2d184f1d72 🔬 Test exec 2018-07-22 01:22:26 +08:00
Felix Rieseberg abc251c318 🔬 Test editor-layout 2018-07-22 00:36:43 +08:00
Felix Rieseberg 001f377e29 🔬 Test devmode 2018-07-21 23:39:15 +08:00
Felix Rieseberg fbad873941 🔬 Test classnames 2018-07-21 23:33:33 +08:00
Felix Rieseberg ac5d34fe92 🔬 Test array-to-stringmap 2018-07-21 23:28:22 +08:00
Felix Rieseberg 7b5ee87c00 📦 Test infrastructure 2018-07-21 23:27:16 +08:00
Felix Rieseberg 1baf6459f1 Merge pull request #36 from electron/tour
feat: A "Welcome to Electron Fiddle" Tour
2018-07-21 23:01:23 +08:00
Felix Rieseberg 9be0559595 🔧 Cleanup 2018-07-21 16:57:33 +08:00
Felix Rieseberg 3dae0bfb44 🚀 Tie it all together 2018-07-21 16:23:14 +08:00
Felix Rieseberg aabf2827c1 🔧 Allow tour forks 2018-07-21 15:39:34 +08:00
Felix Rieseberg 2f77d1f85f 🔧 Better positioning, better look 2018-07-21 15:26:43 +08:00
Felix Rieseberg 14e4f0cf32 🎨 Animate each dialog 2018-07-21 15:22:14 +08:00
Felix Rieseberg ee809369e1 🚀 The tour is taking real shape here 2018-07-20 19:48:08 +08:00
Felix Rieseberg 0026453984 🚀 The tour takes shape 2018-07-20 18:49:35 +08:00
Felix Rieseberg 8f727af18f 🔧 Somewhat fancy positioning tool 2018-07-20 18:49:19 +08:00
Felix Rieseberg de535f3ac5 🚀 Beginnings of a tour 2018-07-20 16:37:26 +08:00
Felix Rieseberg 5a89324bbd 🔧 Make <Dialog /> slightly more generic 2018-07-20 16:36:53 +08:00
Felix Rieseberg c9fd2bfb97 🔧 Fix linter issues 2018-07-20 16:00:52 +08:00
Felix Rieseberg c5f61a8351 🔧 Make appState accessible from the console 2018-07-20 15:59:39 +08:00
Felix Rieseberg 2d55803ba0 🔧 Use it for the tokenDialog 2018-07-20 15:59:19 +08:00
Felix Rieseberg 06f81f0d24 :werench: A generic dialog class 2018-07-20 15:58:49 +08:00
Felix Rieseberg 28c1bf65b6 Merge pull request #35 from electron/make
Add a "Make installers" command
2018-07-19 19:43:08 +08:00
Felix Rieseberg 23f1812e14 Merge pull request #34 from bpasero/bpasero-layout
Avoid lodash#throttle and just use timeouts
2018-07-19 19:39:45 +08:00
Felix Rieseberg f3a1e153cd feat: Allow for "electron-forge make" 2018-07-15 11:14:57 +01:00
Felix Rieseberg 9ca0df0f3e chore: Abstract output operations into state 2018-07-15 11:14:23 +01:00
Felix Rieseberg 1bfa6033d3 feat: Add IPC event for "make" 2018-07-15 11:13:57 +01:00
Benjamin Pasero 03945118ce Avoid lodash#throttle and just use timeouts
fixes https://github.com/electron/fiddle/issues/33
2018-07-13 17:50:52 +02:00
Felix Rieseberg 48f9beba4d Merge pull request #32 from bpasero/bpasero-zoom
Add zooming related actions to the view menu
2018-07-13 10:22:14 +01:00
Benjamin Pasero 02bf3e3837 Add zooming related actions to the view menu
This allows to zoom in, out and reset.
2018-07-13 07:19:04 +02:00
Felix Rieseberg 7bc6fa1ee0 Merge pull request #31 from electron/package
feat: Add a "Package" task
2018-07-12 18:35:13 +01:00
Felix Rieseberg fa8898ed10 feat: Use a fancy name generator 2018-07-12 18:13:03 +01:00
Felix Rieseberg d226f29219 feat: Have terminal always scroll to bottom 2018-07-12 16:53:22 +01:00
Felix Rieseberg df89ff581a feat: Output packaging info to fiddle terminal 2018-07-12 16:53:12 +01:00
Felix Rieseberg 1cf4759483 feat: Basic package command 2018-07-12 16:27:36 +01:00
Felix Rieseberg 9c061b63e2 feat: Abstract saving fiddle to temp folder 2018-07-12 15:59:15 +01:00
Felix Rieseberg 2b92a391fa Merge pull request #30 from electron/forge
feat: Save as Forge Project
2018-07-12 12:58:27 +01:00
Felix Rieseberg cd99cda65c 🔧 Show output item in explorer/finder 2018-07-10 11:09:47 +01:00
Felix Rieseberg 57c0dee597 🔧 Save it all as an actual Forge project 2018-07-10 11:05:45 +01:00
Felix Rieseberg ea3a3473e8 🔧 Add a dotfiles transform 2018-07-10 10:52:21 +01:00
Felix Rieseberg 9c29590c90 🔧 Add a Forge transform 2018-07-10 10:50:35 +01:00
Felix Rieseberg 64c12b7245 🔧 Beef up package.json generation 2018-07-10 10:50:20 +01:00
Felix Rieseberg b996446d1c Merge pull request #29 from electron/transforms
feat: File transforms
2018-07-09 20:11:25 +01:00
Felix Rieseberg 3a928e2f52 🔧 Add file transforms 2018-07-09 11:54:26 +01:00
Felix Rieseberg b328798c93 📝 Update Readme a bit 2018-07-07 08:31:16 +01:00
Felix Rieseberg 3087b57dff 🔧 Default import 2018-07-07 08:20:14 +01:00
Felix Rieseberg 06e46959f8 🔧 Fix /Users/felixr/.nvm/versions/node/v9.8.0/bin:/Users/felixr/Code/go/bin:/usr/local/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/emsdk-portable:/Applications/emsdk-portable/clang/fastcomp/build_incoming_64/bin:/Applications/emsdk-portable/emscripten/incoming on macOS 2018-07-07 08:00:37 +01:00
Felix Rieseberg 67ed669a36 🔧 Fix npm installation 2018-07-06 20:03:55 -04:00
Felix Rieseberg 680c4b140f 📦 Update to alpha 2 2018-07-06 19:44:05 -04:00
Felix Rieseberg 3830828e6f 🔧 Only set noAsar after require 2018-07-06 19:43:59 -04:00
Felix Rieseberg a509763b1e 📦 Update Monaco to 0.13 2018-07-06 18:01:29 -04:00
Felix Rieseberg 4f62229013 🔧 Fix forge config 2018-07-06 12:58:15 -07:00
Felix Rieseberg 42cff3e318 🔧 Update Forge config 2018-07-06 12:45:42 -07:00
Felix Rieseberg 98e7e31b1a 🔧 Save publishing with bad wifi 2018-07-06 12:41:31 -07:00
Felix Rieseberg bede240aee 🔧 Fix preferences position on macOS 2018-07-06 10:47:25 -07:00
Felix Rieseberg ffe9c8fa52 🎨 Use custom milligram, fix CSS issues 2018-07-06 10:45:48 -07:00
Felix Rieseberg 3e3e9be30e 🎨 Include milligram in main css 2018-07-05 17:12:10 -07:00
Felix Rieseberg fa26ec6ffb 🔧 Update downloaded status post-update 2018-07-05 17:12:04 -07:00
Felix Rieseberg 068c4ad14f 🔧 Fancy context menu 2018-07-05 16:58:51 -07:00
Felix Rieseberg abac62c3d8 🔧 Basic context menu 2018-07-05 14:38:49 -07:00
Felix Rieseberg d137a3761f 🔧 Fix missing semicolons 2018-07-05 14:38:42 -07:00
Felix Rieseberg 6980d50192 🎨 Use pre-release FontAwesome 2018-07-05 14:09:06 -07:00
Felix Rieseberg 0c421f0b38 📦 Update Service 2018-07-05 12:03:17 -07:00
Felix Rieseberg 84043e453f 📝 Properly name it all 2018-07-05 11:59:38 -07:00
Felix Rieseberg 45e7cb533e 🚀 Refresh Electron versions on launch 2018-07-05 11:57:42 -07:00
Felix Rieseberg 8fe3875d9a 🔧 Fix FontAwesome import 2018-07-05 11:49:11 -07:00
Felix Rieseberg 3e27cbae84 👷 Improve build 2018-07-05 11:47:56 -07:00
Felix Rieseberg a6e6fad4d9 📦 Use ParcelJS to build 2018-07-05 11:39:45 -07:00
Felix Rieseberg 09928cdeb3 🔧 Lazy-require as much as possible 2018-07-02 19:10:30 -07:00
Felix Rieseberg 49a1d057f2 🔧 Production mode for React & co 2018-07-02 17:41:10 -07:00
Felix Rieseberg 3ee349d8f1 🔧 Entry animation 2018-07-02 17:24:35 -07:00
Felix Rieseberg 00cb6ecf73 🔧 Let editors load Monaco 2018-07-02 15:56:13 -07:00
Felix Rieseberg b6b5c0ac57 🔧 Fix token dialog 2018-07-02 13:58:28 -07:00
Felix Rieseberg 08751d2c61 🔧 Editor: Disable HTML context menu 2018-07-02 12:55:37 -07:00
Felix Rieseberg 0725048f64 🔧 Appease the linter 2018-07-02 12:54:54 -07:00
Felix Rieseberg dc18199790 🔧 Save dependencies to package.json 2018-07-02 12:53:51 -07:00
Felix Rieseberg ef85111944 🔧 Fix contributors script, harder 2018-06-29 12:18:39 -07:00
Felix Rieseberg 2cef76865c 🔧 Fix contributors script 2018-06-29 12:13:08 -07:00
Felix Rieseberg befa3192f4 🎨 Make it all pretty (again) 2018-06-29 12:10:39 -07:00
Felix Rieseberg c21b157469 Merge pull request #28 from electron/file-operations
feat: File operations
2018-06-25 11:23:54 -07:00
Felix Rieseberg 51e7c609da 🔧 Add url display for gists 2018-06-24 21:39:50 -07:00
Felix Rieseberg cc493283bd 🔧 Set window title 2018-06-24 21:39:50 -07:00
Felix Rieseberg 41203ecd17 🔧 Enable "Save to Gist" 2018-06-24 21:39:50 -07:00
Felix Rieseberg d9d5335e93 🔧 Enable "Save as..." 2018-06-24 21:39:50 -07:00
Felix Rieseberg e968219491 🔧 Basic file operations 2018-06-24 21:39:50 -07:00
Felix Rieseberg 5e973723c6 🔧 Add menu and IPC events 2018-06-24 21:39:50 -07:00
Felix Rieseberg 1f6c2e9e89 Merge pull request #27 from electron/darwin-icon
fix: Add macOS icon
2018-06-24 21:37:32 -07:00
Felix Rieseberg bd1f4e9a0d 🎨 Add macOS icon 2018-06-24 19:30:07 -07:00
Felix Rieseberg e829e3a17e Merge pull request #26 from electron/windows-fixes
Add basic File menu, improve Windows CSS
2018-06-24 19:25:34 -07:00
Felix Rieseberg 11bf84189f 🔧 Minor Windows fixes 2018-06-24 19:16:11 -07:00
Felix Rieseberg 12f979b25e Merge pull request #25 from electron/less
Move to less, improve dev tools
2018-06-24 18:57:51 -07:00
Felix Rieseberg 70ae2e1806 🔧 Duh 2018-06-24 18:49:48 -07:00
Felix Rieseberg 546eee8d63 👷 Fix tests 2018-06-24 18:48:03 -07:00
Felix Rieseberg b5ea4a869b 🔧 Slightly better watcher 2018-06-24 18:45:13 -07:00
Felix Rieseberg e95976006e ❤️ Feedback 2018-06-24 18:45:06 -07:00
Felix Rieseberg 97a37ab800 🔧 File watcher 2018-06-24 18:33:49 -07:00
Felix Rieseberg 67aa09e717 🔧 Cleanup 2018-06-24 18:33:42 -07:00
Felix Rieseberg d371e4ee9f 🔧 🎨 Better less, better tools 2018-06-24 18:11:21 -07:00
Felix Rieseberg 4ce070c24b 🔧 Don't check css in 2018-06-24 17:39:40 -07:00
Felix Rieseberg c1320453a0 📦 Install stylelint 2018-06-24 17:38:11 -07:00
Felix Rieseberg b20c31b2da 🎨 Move to less 2018-06-24 17:31:52 -07:00
Felix Rieseberg a789b3fa60 📦 Install less 2018-06-24 17:31:45 -07:00
Felix Rieseberg a814118a19 Merge pull request #23 from electron/protocol-and-windows-stuff
[WIP] Protocol Handler + Windows fixes
2018-06-24 16:51:55 -07:00
Samuel Attard cec54617be add basic electron-fiddle protocol handling 2018-06-24 16:51:28 -07:00
Samuel Attard ac7bf44a25 basic windows packaging config 2018-06-24 16:51:28 -07:00
Samuel Attard 5c98534cd8 fix terminal output rendering on windows 2018-06-24 16:51:01 -07:00
Felix Rieseberg e085e90a7a Merge pull request #24 from electron/cleanup-modules
Remove Blueprint from package.json
2018-06-15 17:47:35 +02:00
Felix Rieseberg ab62d3bc10 📦 Remove Blueprint 2018-06-15 16:01:55 +02:00
Felix Rieseberg 5fe535ca29 Merge pull request #22 from electron/fix-first-version-download
Fix first electron version install
2018-06-15 15:32:35 +02:00
Issac Gerges f3904b0226 Fix BinaryManager so first version download happens in a way AppState can be aware of, not as a side-effect of class construction 2018-06-14 14:57:37 +02:00
Felix Rieseberg 01ae77d64c Merge pull request #21 from electron/whitelist-and-credits-text
Whitelist for credits view, new copy
2018-06-14 13:00:49 +02:00
Felix Rieseberg a74b7ae6d8 🔧 Update Credits view 2018-06-14 12:04:59 +02:00
Felix Rieseberg ccdd8d7fc6 Merge pull request #20 from electron/settings
Preferences
2018-06-13 16:17:32 +02:00
Felix Rieseberg a8a7764d64 🎨 Some last cosmetics 2018-06-13 16:16:58 +02:00
Felix Rieseberg 94ea9fc432 🎨 Some final CSS adjustments 2018-06-13 15:56:03 +02:00
Felix Rieseberg ed66edc612 🎨 Wrap when required 2018-06-13 15:52:14 +02:00
Felix Rieseberg a5c6695c4e 🔧 Insert "Preferences" in correct place 2018-06-13 15:50:22 +02:00
Felix Rieseberg 943d8f314f 🔧 A credits pane 2018-06-13 15:44:49 +02:00
Felix Rieseberg 04c65f0d60 👷 Fetch contributors during build 2018-06-13 15:43:59 +02:00
Felix Rieseberg 7d8983eaea 🔧 Wire up advanced Electron Settings 2018-06-13 12:34:41 +02:00
Felix Rieseberg fd812f9d0b 🚀 Add GitHub settings 2018-06-12 20:57:58 +02:00
Felix Rieseberg e45a25970e 🚀 Add Electron settings 2018-06-12 20:31:42 +02:00
Felix Rieseberg f3e9faa64e 🔧 State: New method: remove version 2018-06-12 20:10:20 +02:00
Felix Rieseberg 516c7e6816 🔧 New binary method: remove 2018-06-12 20:10:06 +02:00
Felix Rieseberg c80bfcc54f 🔧 Add utility: Sorted Electron map 2018-06-12 20:09:53 +02:00
Felix Rieseberg 48fd3960b1 🔧 Basic settings pane 2018-06-12 19:08:26 +02:00
Felix Rieseberg 2691486e73 📝 Document the token dialog class 2018-06-12 15:30:36 +02:00
Felix Rieseberg e66116cdb4 🔧 Store more GitHub information 2018-06-12 15:26:38 +02:00
Felix Rieseberg 3d1450f35a Merge pull request #19 from electron/graceful-opening
Graceful opening, central IPC, cleaner menu
2018-06-12 15:19:53 +02:00
Felix Rieseberg 1d010be01f 🔧 Move files around, add menu, add graceful opening 2018-06-12 15:17:10 +02:00
Felix Rieseberg 1214963212 🔧 Make a central place for IPC calls 2018-06-12 15:16:51 +02:00
Felix Rieseberg e4f8c3d434 🔧 Make sure dialogs don’t eat clicks 2018-06-12 15:16:09 +02:00
Felix Rieseberg 5ea418f18e Merge pull request #18 from electron/publish-improvements
Improve login/publish flow
2018-06-12 11:25:29 +02:00
Felix Rieseberg aad2b26de8 🔧 Make it all reactive 2018-06-11 23:15:58 +02:00
Felix Rieseberg 00d1b3c56d 🎨 Rework token dialog 2018-06-11 22:50:59 +02:00
Felix Rieseberg 74ea847327 🎨 Fix modal button color 2018-06-11 21:27:36 +02:00
Felix Rieseberg e53b40ca08 🔧 Cut login button, always use publish button 2018-06-11 21:19:35 +02:00
Felix Rieseberg bc79c66526 Merge pull request #17 from electron/windows-improvements
Allow app to start on Windows
2018-06-10 19:03:41 +02:00
Felix Rieseberg 1a1f01f639 🔧 Allow app to run on Windows 2018-06-10 18:34:47 +02:00
Felix Rieseberg a89d5ef91c Merge pull request #16 from electron/docs
Docs: Code of conduct, security
2018-06-10 14:34:54 +02:00
Felix Rieseberg 6aee1b1d68 📝 Various default files 2018-06-10 14:33:02 +02:00
Felix Rieseberg 055d6cc548 🔧 Fix handler context 2018-06-09 17:53:30 +02:00
Felix Rieseberg 9b86273aad Merge pull request #15 from electron/code-cleanup
Documentation, minor code cleanup
2018-06-09 17:52:19 +02:00
Felix Rieseberg 5cdebdd86a 💂‍♂️ Cleanup code, document it 2018-06-09 17:20:23 +02:00
Felix Rieseberg 689ef5d926 Merge pull request #14 from electron/60fps
60fps
2018-06-09 11:04:34 +02:00
Felix Rieseberg 8241c29521 🚀 60fps 2018-06-09 09:35:15 +02:00
Felix Rieseberg 2bebba5ff6 Merge pull request #13 from electron/window-management
Improved window management
2018-06-09 08:23:56 +02:00
Felix Rieseberg 7d8b7c6ed3 🎨 Fix console scrollbar 2018-06-08 17:23:55 +02:00
Felix Rieseberg 38dc15c1ab 🎨 Remove controls 2018-06-08 17:17:50 +02:00
Felix Rieseberg 9d65cc1083 🚀 First version of window management 2018-06-08 17:13:32 +02:00
Felix Rieseberg 260ada1ced Merge pull request #12 from electron/so-many-changes
Address bar, classnames, optics
2018-06-08 14:23:38 +02:00
Felix Rieseberg a04030904f 🚀 Make an address bar 2018-06-08 14:12:58 +02:00
Felix Rieseberg d5143a9224 📦 Add classnames 2018-06-08 14:12:45 +02:00
Felix Rieseberg 60df3aecc4 🔧 Add gist utilities 2018-06-08 14:12:28 +02:00
Felix Rieseberg 7016affadf 🔧 Update .gitignore 2018-06-08 14:11:42 +02:00
Felix Rieseberg d32f9af011 Merge pull request #11 from electron/more-gist
feat: token validation and basic publish/load gist logic
2018-06-08 09:05:28 +02:00
Samuel Attard bbbe7266af feat: token validation and basic publish/load gist logic 2018-06-08 01:17:49 +02:00
Felix Rieseberg 67b2819a85 Merge pull request #10 from electron/default-menu
Default menu, resizable editors
2018-06-07 18:03:01 +02:00
Felix Rieseberg 851ca5b390 🔧 Make editors resizable 2018-06-07 18:01:11 +02:00
Felix Rieseberg a28b9d34da 🔧 Add an app menu 2018-06-07 18:01:01 +02:00
Felix Rieseberg faf9c96fe2 Merge pull request #9 from electron/gist-token-auth
Rough draft: Accept a GitHub Gist token
2018-06-07 16:56:05 +02:00
Charlie Hess 344382a18d I'm real bad at CSS. 2018-06-07 15:28:33 +02:00
Charlie Hess 1865f66e29 Make it kinda work. 2018-06-07 15:28:27 +02:00
Charlie Hess fd458adc5e Fix an unrelated "child elements need key" error. 2018-06-07 15:28:03 +02:00
Felix Rieseberg 57b00c8126 Merge pull request #8 from electron/active-button
Fix color for active button
2018-06-07 14:18:36 +02:00
Felix Rieseberg dcbc9eff88 Merge pull request #7 from electron/type-definitions
Add TypeScript definitions for Electron
2018-06-07 14:17:43 +02:00
Felix Rieseberg b52ee70dde Merge pull request #6 from electron/better-tsc
build: use better tsc in build phase
2018-06-07 14:17:34 +02:00
Felix Rieseberg 316077e3b7 🎨 Fix color for active button 2018-06-07 14:17:04 +02:00
Felix Rieseberg 80993f2cac 🔧 Add TypeScript definitions for Electron 2018-06-07 14:09:23 +02:00
Samuel Attard 59ac41b369 build: use better tsc in build phase 2018-06-07 14:07:40 +02:00
Charlie Hess 6dffdef8f0 Add an auth button in the header. 2018-06-07 14:01:03 +02:00
394 changed files with 50564 additions and 5575 deletions
+4
View File
@@ -0,0 +1,4 @@
/out
/dist
/coverage
/static
+30
View File
@@ -0,0 +1,30 @@
module.exports = {
parser: '@typescript-eslint/parser', // Specifies the ESLint parser
parserOptions: {
ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
sourceType: 'module', // Allows for the use of imports
ecmaFeatures: {
jsx: true, // Allows for the parsing of JSX
},
},
settings: {
react: {
version: 'detect', // Tells eslint-plugin-react to automatically detect the version of React to use
},
},
extends: [
'plugin:react/recommended', // Uses the recommended rules from @eslint-plugin-react
'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin
'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier
'plugin:prettier/recommended', // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
],
rules: {
// Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
// e.g. "@typescript-eslint/explicit-function-return-type": "off",
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
},
};
+1
View File
@@ -0,0 +1 @@
* text=auto
+31
View File
@@ -0,0 +1,31 @@
const { Octokit } = require('@octokit/action')
const octokit = new Octokit()
const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/')
async function main () {
const prs = await octokit.pulls.list({
owner,
repo,
state: 'open',
head: `${owner}:update-releases`
})
if (prs.data.length === 0) {
const pr = await octokit.pulls.create({
owner,
repo,
title: 'build: update Electron releases JSON',
base: 'master',
head: 'update-releases',
body: 'Auto-update from GitHub Actions.',
maintainer_can_modify: true
})
console.log('Pull request created:', pr.html_url)
} else {
console.log('Pull request updated:', prs.data[0].html_url)
}
}
main()
+51
View File
@@ -0,0 +1,51 @@
name: Auto-update Releases JSON file
on:
schedule:
- cron: '0 0 * * 1'
jobs:
autoupdate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Fetch git branches
run: git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
- uses: actions/setup-node@v1
with:
node-version: '12.x'
- name: Get npm cache directory
id: npm-cache
run: |
echo "::set-output name=dir::$(npm config get cache)"
- uses: actions/cache@v1
with:
path: ${{ steps.npm-cache.outputs.dir }}
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- run: npm ci
- name: Switch to release update branch
run: |
if git branch --remotes | grep -q origin/update-releases; then
git checkout update-releases
else
git checkout -b update-releases
fi
- name: Update Releases JSON
run: npm run electron-releases
- name: Commit Changes to Releases JSON
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "machine github.com login $GITHUB_ACTOR password $GITHUB_TOKEN" > ~/.netrc
chmod 600 ~/.netrc
git add static/releases.json tests/fixtures/releases-metadata.json
if test -n "$(git status -s)"; then
git config user.name "$GITHUB_ACTOR"
git config user.email "electron-bot@users.noreply.github.com"
git diff --cached
git commit -m "build: update Electron releases JSON"
git push origin update-releases
node --unhandled-rejections=strict .github/actions/create_releases_pr.js
else
echo No update needed
fi
+43 -3
View File
@@ -1,3 +1,43 @@
node_modules
out
dist
.DS_Store
.env
.gclient_done
**/.npmrc
.tags*
.vs/
.vscode/
*.log
*.pyc
*.sln
*.swp
*.VC.db
*.VC.VC.opendb
*.vcxproj
*.vcxproj.filters
*.vcxproj.user
*.xcodeproj
/.idea/
/dist/
/external_binaries/
/out/
node_modules/
SHASUMS256.txt
**/yarn.lock
compile_commands.json
.envrc
.cache
yarn-error.log
.DS_Store
# Coverage
coverage
# Test report
report.json
# npm package
/npm/dist
/npm/path.txt
# Electron Fiddle-Specific
/static/contributors.json
/static/css/root.css
+4
View File
@@ -0,0 +1,4 @@
module.exports = {
trailingComma: "all",
singleQuote: true,
};
+7
View File
@@ -0,0 +1,7 @@
{
"extends": "stylelint-config-standard",
"ignoreFiles": [
"./src/less/*-vendor.less"
],
"rules": { }
}
+38 -8
View File
@@ -1,15 +1,14 @@
language: node_js
node_js: "8"
node_js: "12"
os:
- linux
- osx
dist: trusty
osx_image: xcode8.3
sudo: false
dist: bionic
osx_image: xcode10
cache:
npm: true
directories:
- node_modules
- $HOME/.cache/electron
addons:
@@ -24,10 +23,41 @@ branches:
- /^v\d+\.\d+\.\d+/
install:
- npm install
- npm update
- npm ci
- |
if [[ "$TRAVIS_OS_NAME" == "osx" && "$TRAVIS_SECURE_ENV_VARS" == "true" ]]; then
export CERTIFICATE_P12=cert.p12;
echo $MACOS_CERT_P12 | base64 --decode > $CERTIFICATE_P12;
export KEYCHAIN=build.keychain;
# Create the keychain with a password
security create-keychain -p travis $KEYCHAIN;
# Make the custom keychain default, so xcodebuild will use it for signing
security default-keychain -s $KEYCHAIN;
# Unlock the keychain
security unlock-keychain -p travis $KEYCHAIN;
# Add certificates to keychain and allow codesign to access them
# Apple Worldwide Developer Relations Certification Authority
security import ./tools/certs/apple.cer -k ~/Library/Keychains/$KEYCHAIN -T /usr/bin/codesign
# Developer Authentication Certification Authority
security import ./tools/certs/dac.cer -k ~/Library/Keychains/$KEYCHAIN -T /usr/bin/codesign
# Developer ID Felix
security import $CERTIFICATE_P12 -k $KEYCHAIN -P $MACOS_CERT_PASSWORD -T /usr/bin/codesign 2>&1 >/dev/null;
rm $CERTIFICATE_P12;
security set-key-partition-list -S apple-tool:,apple: -s -k travis $KEYCHAIN
# Echo the identity
security find-identity -v -p codesigning
fi
script:
- npm run lint
- npm run test:ci
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then npm run test:coverage; fi
- if test -z "$TRAVIS_TAG"; then npm run make; fi
after_success: if test -n "$TRAVIS_TAG"; then npm run publish; fi
after_success: if test -n "$TRAVIS_TAG"; then npm run publish; fi
+46
View File
@@ -0,0 +1,46 @@
# Contributor Covenant Code of Conduct:
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [coc@electronjs.org](mailto:coc@electronjs.org). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor-Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version]
[homepage]: https://contributor-covenant.org
[version]: https://contributor-covenant.org/version/1/4/
+74
View File
@@ -0,0 +1,74 @@
# Contributing to Electron Fiddle
Electron Fiddle is a community-driven project, overseen by the [Electron Ecosystem Working
Group](https://github.com/electron/governance/tree/master/wg-ecosystem#readme). As such, we welcome
and encourage all sorts of contributions. They include, but are not limited to:
- Constructive feedback
- Bug reports / technical issues
- Documentation changes
- Feature requests
- [Pull requests](#filing-pull-requests)
We strongly suggest that before filing an issue, you search through the existing issues to see
if it has already been filed by someone else.
This project is a part of the Electron ecosystem. As such, all contributions to this project follow
[Electron's code of conduct](https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md)
where appropriate.
## Contribution Suggestions
We use the label [`good first issue`](https://github.com/electron/fiddle/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) in the issue tracker to denote fairly-well-scoped-out bugs or feature requests that the community can pick up and work on. If any of those labeled issues do not have enough information, please feel free to ask constructive questions. (This applies to any open issue.)
## Filing Pull Requests
Here are some things to keep in mind as you file pull requests to fix bugs, add new features, etc.:
* If you're unfamiliar with forking, branching, and pull requests, please see [GitHub's extensive
documentation](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests).
* Travis CI and AppVeyor are used to make sure that any new or changed code meets the project's
style guidelines, and that the project's testsuite passes for each new commit.
* Unless it's impractical, please write tests for your changes. This will help us so that we can
spot regressions much easier.
* When creating commit messages and pull request titles, please adhere to the [conventional
commits](https://www.conventionalcommits.org/en/v1.0.0/) standard.
* Please **do not** bump the version number in your pull requests, the maintainers will do that.
Feel free to indicate whether the changes require a major, minor, or patch version bump, as
prescribed by the [semantic versioning specification](http://semver.org/).
### Running Fiddle From Source
1. Clone the Electron Fiddle repository locally.
```sh
git clone https://github.com/electron/fiddle.git
```
2. Change directory to where Fiddle has been cloned.
```sh
cd fiddle
```
3. Install dependencies.
```sh
npm install
```
4. Start Fiddle and Explore!
```sh
npm start
```
### Running Tests
```sh
npm test
```
## Release Process
<!-- TODO @felix add your release process here 😁 -->
+2 -2
View File
@@ -1,4 +1,4 @@
Copyright (c) 2013-2018 GitHub Inc.
Copyright (c) 2013-2020 GitHub Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+72 -3
View File
@@ -1,5 +1,74 @@
# Electron Fiddle
# <img src="https://user-images.githubusercontent.com/378023/49785546-4b7f7000-fd64-11e8-8033-a52c73a07fbf.png" width="60px" align="center" alt="Electron Fiddle icon"> Electron Fiddle
> Still a work in progress, please stay tuned.
[![Build Status](https://travis-ci.org/electron/fiddle.svg?branch=master)](https://travis-ci.org/electron/fiddle)
[![Coverage Status](https://coveralls.io/repos/github/electron/fiddle/badge.svg?branch=master)](https://coveralls.io/github/electron/fiddle?branch=master)
[![Electron Discord Invite](https://img.shields.io/discord/745037351163527189?color=%237289DA&label=chat&logo=discord&logoColor=white)](https://discord.com/invite/electron)
![](https://user-images.githubusercontent.com/1426799/41096018-8499e31a-6a53-11e8-9887-7483fd38e58b.png)
Electron Fiddle lets you create and play with small Electron experiments. It
greets you with a quick-start template after opening change a few things,
choose the version of Electron you want to run it with, and play around. Then,
save your Fiddle either as a GitHub Gist or to a local folder. Once published
on GitHub, anyone can quickly try your Fiddle out by just entering it in the
address bar.
<h3 align="center">
<a href="https://github.com/electron/fiddle/releases/latest">
Download Electron Fiddle for macOS, Windows, and Linux
</a>
</h3>
<img src="https://user-images.githubusercontent.com/1426799/52155868-d3357c80-2639-11e9-9496-fa97b1dc7897.jpg" width="880px" alt="Electron Fiddle screenshot">
# Features
### Explore Electron
![Screenshot: Electron App running](https://user-images.githubusercontent.com/1426799/52155856-c0bb4300-2639-11e9-9962-a6354d08dc5a.jpg)
Try Electron without installing any dependencies: Fiddle includes everything
you'll need to explore the platform. It also includes examples for every API
available in Electron, so if you want to quickly see what a
[BrowserView][BrowserView] is or how the [desktopCapturer][desktopCapturer]
works, Fiddle has got you covered.
### Code with Types
![Screenshot: Fiddle's Types](https://user-images.githubusercontent.com/1426799/43874324-10e46eae-9b40-11e8-962b-8c793d73c259.png)
Fiddle includes Microsoft's excellent Monaco Editor, the same editor powering
Visual Studio Code. It also installs the type definitions for the currently
selected version of Electron automatically, ensuring that you always have
all Electron APIs only a few keystrokes away.
### Compile and Package
![Screenshot: Fiddle's Tasks Menu](https://user-images.githubusercontent.com/1426799/52155857-c0bb4300-2639-11e9-8776-e05dc528439c.png)
Fiddle can automatically turn your experiment into binaries you can share with
your friends, coworkers, or grandparents. It does so thanks to
[electron-forge][electron-forge], allowing you to package your fiddle as an
app for Windows, macOS, or Linux.
### Start with Fiddle, Continue Wherever
![Screenshot: Visual Studio Code with Fiddle Export](https://user-images.githubusercontent.com/1426799/43874411-9cfd5946-9b40-11e8-8797-dd4138e31933.png)
Fiddle is not an IDE  it is however an excellent starting point. Once your
fiddle has grown up, export it as a project with or without
[electron-forge][electron-forge]. Then, use your favorite editor and take on
the world!
## Contributing
Electron Fiddle is a community-driven project that welcomes all sorts of contributions. Please check out our [Contributing Guide](https://github.com/electron/fiddle/blob/master/CONTRIBUTING.md) for more details.
## License
[MIT, please see the LICENSE file for full details](https://github.com/electron/fiddle/blob/master/LICENSE.md).
When using the Electron or other GitHub logos, be sure to follow the [GitHub
logo guidelines](https://github.com/logos).
[BrowserView]: https://electronjs.org/docs/api/browser-view
[desktopCapturer]: https://electronjs.org/docs/api/desktop-capturer
[electron-forge]: https://electronforge.io/
+12
View File
@@ -0,0 +1,12 @@
# Reporting Security Issues
The Electron team and community take security bugs in Electron seriously. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions.
To report a security issue, email [security@electronjs.org](mailto:security@electronjs.org) and include the word "SECURITY" in the subject line.
The Electron team will send a response indicating the next steps in handling your report. After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance.
Report security bugs in third-party modules to the person or team maintaining the module. You can also report a vulnerability through the [Node Security Project](https://nodesecurity.io/report).
## Learning More About Security
To learn more about securing an Electron application, please see the [security tutorial](https://github.com/electron/electron/blob/master/docs/tutorial/security.md).
+37
View File
@@ -0,0 +1,37 @@
environment:
matrix:
- nodejs_version: "12"
init:
- git config --global core.symlinks true
install:
# Setup the code signing certificate
- ps: >-
if (Test-Path Env:\WINDOWS_CERTIFICATE_P12) {
$workingDirectory = Convert-Path (Resolve-Path -path ".")
$filename = "$workingDirectory\cert.p12"
$bytes = [Convert]::FromBase64String($env:WINDOWS_CERTIFICATE_P12)
[IO.File]::WriteAllBytes($filename, $bytes)
}
- ps: Install-Product node $env:nodejs_version x64
- node --version
- npm ci
cache:
- '%APPDATA%\npm-cache -> appveyor.yml'
test_script:
- node --version
- npm --version
- npm run lint
- npm run test
artifacts:
- path: 'out\make\squirrel.windows\**\*.exe'
build_script:
- if %APPVEYOR_REPO_TAG% EQU false npm run make
- if %APPVEYOR_REPO_TAG% EQU true npm run publish
- if %APPVEYOR_REPO_TAG% EQU true npm run publish -- --arch=ia32
- ps: Tree ./out/make /F
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="1024px" height="1024px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="SVG" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icon">
<circle id="BG" stroke="#FFFFFF" stroke-width="36" fill="#E79537" cx="512" cy="512" r="430"></circle>
<g id="Glyph" transform="translate(336.000000, 280.000000)">
<path d="M92,335.02442 L92,44 C92,30.745166 102.745166,20 116,20 L356,20 C369.254834,20 380,30.745166 380,44 C380,57.254834 369.254834,68 356,68 L140,68 L140,188 L239.428571,188 C250.789858,188 260,198.745166 260,212 C260,225.254834 250.789858,236 239.428571,236 L140,236 L140,335.02442 C181.405453,345.681447 212,383.267854 212,428 C212,481.019336 169.019336,524 116,524 C62.980664,524 20,481.019336 20,428 C20,383.267854 50.5945469,345.681447 92,335.02442 Z" id="Shadow" fill="#000000" fill-rule="nonzero" opacity="0.0980980283"></path>
<path d="M72,315.02442 L72,24 C72,10.745166 82.745166,0 96,0 L336,0 C349.254834,0 360,10.745166 360,24 C360,37.254834 349.254834,48 336,48 L120,48 L120,168 L219.428571,168 C230.789858,168 240,178.745166 240,192 C240,205.254834 230.789858,216 219.428571,216 L120,216 L120,315.02442 C161.405453,325.681447 192,363.267854 192,408 C192,461.019336 149.019336,504 96,504 C42.980664,504 0,461.019336 0,408 C0,363.267854 30.5945469,325.681447 72,315.02442 Z" id="Path" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M96,456 C122.509668,456 144,434.509668 144,408 C144,381.490332 122.509668,360 96,360 C69.490332,360 48,381.490332 48,408 C48,434.509668 69.490332,456 96,456 Z" id="Dot" fill="#EB5E00"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

+130 -22
View File
@@ -1,27 +1,94 @@
/* tslint:disable */
const path = require('path');
const fs = require('fs');
const packageJson = require('./package.json');
module.exports = {
packagerConfig: {},
const { version } = packageJson;
const iconDir = path.resolve(__dirname, 'assets', 'icons');
const config = {
hooks: {
generateAssets: require('./tools/generateAssets'),
},
packagerConfig: {
name: 'Electron Fiddle',
executableName: 'electron-fiddle',
asar: true,
icon: path.resolve(__dirname, 'assets', 'icons', 'fiddle'),
appBundleId: 'com.electron.fiddle',
usageDescription: {
Camera:
'Access is needed by certain built-in fiddles in addition to any custom fiddles that use the Camera',
Microphone:
'Access is needed by certain built-in fiddles in addition to any custom fiddles that use the Microphone',
},
appCategoryType: 'public.app-category.developer-tools',
protocols: [
{
name: 'Electron Fiddle Launch Protocol',
schemes: ['electron-fiddle'],
},
],
win32metadata: {
CompanyName: 'Electron Community',
OriginalFilename: 'Electron Fiddle',
},
osxSign: {
identity: 'Developer ID Application: Felix Rieseberg (LT94ZKYDCJ)',
'hardened-runtime': true,
'gatekeeper-assess': false,
entitlements: 'static/entitlements.plist',
'entitlements-inherit': 'static/entitlements.plist',
'signature-flags': 'library',
},
},
makers: [
{
name: "@electron-forge/maker-squirrel",
platforms: ["win32"],
name: '@electron-forge/maker-squirrel',
platforms: ['win32'],
config: (arch) => {
const certificateFile = process.env.CI
? path.join(__dirname, 'cert.p12')
: process.env.WINDOWS_CERTIFICATE_FILE;
if (!certificateFile || !fs.existsSync(certificateFile)) {
console.warn(
`Warning: Could not find certificate file at ${certificateFile}`,
);
}
return {
name: 'electron-fiddle',
authors: 'Electron Community',
exe: 'electron-fiddle.exe',
iconUrl:
'https://raw.githubusercontent.com/electron/fiddle/0119f0ce697f5ff7dec4fe51f17620c78cfd488b/assets/icons/fiddle.ico',
loadingGif: './assets/loading.gif',
noMsi: true,
remoteReleases: '',
setupExe: `electron-fiddle-${version}-${arch}-setup.exe`,
setupIcon: path.resolve(iconDir, 'fiddle.ico'),
certificatePassword: process.env.WINDOWS_CERTIFICATE_PASSWORD,
certificateFile,
};
},
},
{
name: '@electron-forge/maker-zip',
platforms: ['darwin'],
},
{
name: '@electron-forge/maker-deb',
platforms: ['linux'],
config: {
name: "electron_fiddle"
}
icon: {
scalable: path.resolve(iconDir, 'fiddle.svg'),
},
},
},
{
name: "@electron-forge/maker-zip",
platforms: ["darwin"]
name: '@electron-forge/maker-rpm',
platforms: ['linux'],
},
{
name: "@electron-forge/maker-deb",
platforms: ["linux"]
},
{
name: "@electron-forge/maker-rpm",
platforms: ["linux"]
}
],
publishers: [
{
@@ -29,10 +96,51 @@ module.exports = {
config: {
repository: {
owner: 'electron',
name: 'fiddle'
name: 'fiddle',
},
prerelease: true
}
}
]
draft: true,
prerelease: false,
},
},
],
};
function notarizeMaybe() {
if (process.platform !== 'darwin') {
return;
}
if (process.env.npm_lifecycle_event !== 'publish') {
console.log(`Not in "publish" mode, skipping notarization`);
return;
}
if (!process.env.CI) {
console.log(`Not in CI, skipping notarization`);
return;
}
if (!process.env.TRAVIS_TAG && !process.env.NOTARIZE_WITHOUT_TAG) {
console.log(`Not a tag, not notarizing`);
return;
}
if (!process.env.APPLE_ID || !process.env.APPLE_ID_PASSWORD) {
console.warn(
'Should be notarizing, but environment variables APPLE_ID or APPLE_ID_PASSWORD are missing!',
);
return;
}
config.packagerConfig.osxNotarize = {
appBundleId: 'com.electron.fiddle',
appleId: process.env.APPLE_ID,
appleIdPassword: process.env.APPLE_ID_PASSWORD,
ascProvider: 'LT94ZKYDCJ',
};
}
notarizeMaybe();
// Finally, export it
module.exports = config;
+43
View File
@@ -0,0 +1,43 @@
{
"transform": {
"\\.(js|jsx|ts|tsx)$": "ts-jest"
},
"testURL": "http://localhost",
"testRegex": "(-spec)\\.(ts|tsx)$",
"resetMocks": true,
"bail": true,
"resetModules": true,
"snapshotSerializers": [
"enzyme-to-json/serializer"
],
"setupFilesAfterEnv": [
"<rootDir>/tests/setup.js"
],
"moduleFileExtensions": [
"js",
"jsx",
"json",
"ts",
"tsx"
],
"testPathIgnorePatterns": [
"/.tmp/"
],
"coverageReporters": [
"json",
"html",
"lcov"
],
"collectCoverageFrom": [
"src/**/*.{ts,tsx}",
"!**/*.d.ts",
"!**/*constants.ts"
],
"coveragePathIgnorePatterns": [
"/node_modules/",
"/tests/.*\\.(ts|js)$"
],
"moduleNameMapper": {
".*releases.json$": "<rootDir>/static/releases.json"
}
}
+18986 -4024
View File
File diff suppressed because it is too large Load Diff
+112 -48
View File
@@ -1,66 +1,130 @@
{
"name": "electron-fiddle",
"productName": "electron-fiddle",
"version": "1.0.0",
"description": "My Electron application description",
"productName": "Electron Fiddle",
"version": "0.16.0",
"description": "The easiest way to get started with Electron",
"repository": "https://github.com/electron/fiddle",
"main": "./dist/main",
"main": "./dist/src/main/main",
"scripts": {
"build": "tsc -p tsconfig.json",
"start": "npm run build && electron-forge start",
"package": "electron-forge package",
"contributors": "node ./tools/contributors.js",
"less": "node ./tools/lessc.js",
"lint:style": "stylelint \"./src/less/*.less\" --fix",
"lint:ts": "eslint \"./**/*.{js,ts,tsx}\" --fix",
"lint:templates": "standard \"./static/show-me/**/*.js\" --fix",
"lint": "npm-run-all \"lint:*\"",
"make": "electron-forge make",
"package": "electron-forge package",
"parcel:build": "node ./tools/parcel-build.js",
"parcel:watch": "node ./tools/parcel-watch.js",
"publish": "electron-forge publish",
"lint": "tslint -c tslint.json -p tsconfig.json -e \"node_modules/**/*.ts\""
"start": "rimraf ./dist && electron-forge start",
"test": "jest --config=jest.json",
"test:ci": "jest --config=jest.json --coverage --runInBand",
"test:coverage": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js",
"test:report": "jest --config=jest.json --json --bail=false --outputFile=report.json | true",
"tsc": "tsc --noEmit -p .",
"electron-releases": "node --unhandled-rejections=strict ./tools/fetch-releases.js"
},
"keywords": [],
"author": "felixr",
"keywords": [
"Electron",
"Fiddle",
"Tutorial"
],
"author": "Felix Rieseberg <felix@felixrieseberg.com>",
"license": "MIT",
"config": {
"forge": "./forge.config.js"
},
"dependencies": {
"@fortawesome/fontawesome": "^1.1.8",
"@fortawesome/fontawesome-free-solid": "^5.0.13",
"@fortawesome/react-fontawesome": "0.0.20",
"@octokit/rest": "^15.8.1",
"builtin-modules": "^3.0.0",
"electron-download": "^4.1.0",
"@blueprintjs/core": "^3.24.0",
"@blueprintjs/select": "^3.12.0",
"@electron/get": "^1.9.0",
"@octokit/rest": "^16.43.1",
"@sentry/electron": "^1.2.1",
"classnames": "^2.2.6",
"electron-default-menu": "^1.0.2",
"electron-devtools-installer": "^3.1.1",
"electron-squirrel-startup": "^1.0.0",
"extract-zip": "^1.6.7",
"fs-extra": "^6.0.1",
"loader-utils": "^1.1.0",
"milligram": "^1.3.0",
"mobx": "^4.3.1",
"mobx-react": "^5.2.0",
"monaco-loader": "^0.8.2",
"react": "^16.4.0",
"react-dom": "^16.4.0",
"semver": "^5.5.0",
"tmp": "0.0.33",
"tslib": "^1.9.2",
"update-electron-app": "^1.2.0"
"fix-path": "^3.0.0",
"fs-extra": "^8.1.0",
"mobx": "^5.15.4",
"mobx-react": "^6.1.8",
"monaco-editor": "^0.20.0",
"monaco-loader": "1.0.0",
"namor": "^2.0.2",
"react": "^16.13.0",
"react-dom": "^16.13.0",
"react-mosaic-component": "^3.2.0",
"semver": "^7.1.3",
"tmp": "0.1.0",
"tslib": "^1.11.1",
"update-electron-app": "^2.0.1"
},
"devDependencies": {
"@electron-forge/cli": "^6.0.0-beta.17",
"@electron-forge/maker-deb": "^6.0.0-beta.17",
"@electron-forge/maker-rpm": "^6.0.0-beta.17",
"@electron-forge/maker-squirrel": "^6.0.0-beta.17",
"@electron-forge/maker-zip": "^6.0.0-beta.17",
"@types/builtin-modules": "^2.0.0",
"@types/fs-extra": "^5.0.2",
"@types/node": "^10.3.1",
"@types/react": "^16.3.16",
"@types/react-dom": "^16.0.6",
"@types/semver": "^5.5.0",
"@types/tmp": "0.0.33",
"css-loader": "^0.28.11",
"electron": "2.0.2",
"monaco-editor": "^0.13.1",
"style-loader": "^0.21.0",
"tslint": "^5.10.0",
"tslint-microsoft-contrib": "^5.0.3",
"tslint-react": "^3.6.0",
"typescript": "^2.9.1"
"@babel/core": "^7.8.6",
"@electron-forge/cli": "^6.0.0-beta.52",
"@electron-forge/maker-deb": "^6.0.0-beta.52",
"@electron-forge/maker-rpm": "^6.0.0-beta.52",
"@electron-forge/maker-squirrel": "^6.0.0-beta.52",
"@electron-forge/maker-zip": "^6.0.0-beta.52",
"@electron-forge/publisher-github": "^6.0.0-beta.52",
"@octokit/action": "^2.0.0",
"@types/classnames": "^2.2.9",
"@types/enzyme": "^3.10.5",
"@types/fs-extra": "^8.1.0",
"@types/jest": "^25.1.3",
"@types/log-symbols": "^3.0.0",
"@types/node": "^13.7.6",
"@types/react": "^16.9.23",
"@types/react-dom": "^16.9.5",
"@types/semver": "^7.1.0",
"@types/tmp": "0.1.0",
"@typescript-eslint/eslint-plugin": "^3.7.0",
"@typescript-eslint/parser": "^3.7.0",
"chokidar": "^3.3.1",
"coveralls": "^3.0.9",
"electron": "^9.3.1",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
"enzyme-to-json": "^3.4.4",
"eslint": "^7.5.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-react": "^7.20.3",
"fetch-mock-jest": "^1.1.0-beta.3",
"husky": "^4.2.5",
"jest": "^25.1.0",
"less": "^3.11.1",
"lint-staged": "^10.2.11",
"log-symbols": "^3.0.0",
"node-abi": "^2.18.0",
"node-fetch": "^2.6.1",
"npm-run-all": "^4.1.5",
"parcel-bundler": "^1.12.4",
"prettier": "^2.0.5",
"react-test-renderer": "^16.13.0",
"rimraf": "^3.0.0",
"standard": "^14.3.1",
"stylelint": "^13.2.0",
"stylelint-config-standard": "^20.0.0",
"ts-jest": "^25.2.1",
"typescript": "^3.8.2"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"./**/*.{js,ts,tsx}": [
"eslint --fix"
],
"./static/show-me/**/*.js": [
"standard --fix"
],
"./src/less/*.less": [
"stylelint --fix"
]
}
}
+2
View File
@@ -0,0 +1,2 @@
declare module 'fix-path';
declare module 'namor';
+15
View File
@@ -0,0 +1,15 @@
import * as MonacoType from 'monaco-editor';
// Type-only-import
import { App as AppType } from './renderer/app';
import { EditorId } from './interfaces';
declare global {
interface Window {
ElectronFiddle: {
app: AppType;
contentChangeListeners: Array<any>;
editors: Record<EditorId, MonacoType.editor.IStandaloneCodeEditor | null>;
};
}
}
+3 -2
View File
@@ -1,8 +1,9 @@
<!DOCTYPE html>
export const html = `<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<link rel="stylesheet" type="text/css" href="./styles.css">
</head>
<body>
<h1>Hello World!</h1>
@@ -16,4 +17,4 @@
require('./renderer.js')
</script>
</body>
</html>
</html>`;
@@ -1,27 +1,21 @@
// Modules to control application life and create native browser window
export const main = `// Modules to control application life and create native browser window
const {app, BrowserWindow} = require('electron')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
const path = require('path')
const url = require('url')
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({width: 800, height: 600})
const mainWindow = new BrowserWindow({width: 800, height: 600})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
mainWindow.loadURL(url.format({
protocol: 'file',
slashes: true,
pathname: path.resolve(app.getAppPath(), 'index.html')
}))
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
@@ -41,10 +35,10 @@ app.on('window-all-closed', function () {
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
// code. You can also put them in separate files and require them here.`;
+44
View File
@@ -0,0 +1,44 @@
export const main = `// Modules to control application life and create native browser window
const {app, BrowserWindow} = require('electron')
function createWindow () {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow)
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.`;
+3
View File
@@ -0,0 +1,3 @@
export const renderer = `// This file is required by the index.html file and will
// be executed in the renderer process for that window.
// All of the Node.js APIs are available in this process.`;
+111 -18
View File
@@ -1,27 +1,120 @@
export interface StringMap<T> {
[x: string]: T;
export type WindowNames = 'main';
export type Files = Map<string, string>;
export type FileTransform = (files: Files) => Promise<Files>;
export enum VersionState {
ready = 'ready',
downloading = 'downloading',
unzipping = 'unzipping',
unknown = 'unknown',
}
export type ElectronVersionState = 'downloading' | 'ready' | 'unknown';
export interface GitHubVersion {
url: string;
assets_url: string;
html_url: string;
tag_name: string;
target_commitish: string;
name: string;
prerelease: boolean;
created_at: string;
published_at: string;
body: string;
export enum VersionSource {
remote = 'remote',
local = 'local',
}
export interface ElectronVersion extends GitHubVersion {
state: ElectronVersionState;
export enum GistActionType {
publish = 'Publish',
update = 'Update',
delete = 'Delete',
}
export enum GistActionState {
publishing = 'publishing',
updating = 'updating',
deleting = 'deleting',
none = 'none',
}
export interface Version {
version: string;
name?: string;
localPath?: string;
}
export interface EditorValues {
main: string;
renderer: string;
html: string;
preload: string;
css: string;
package?: string;
}
export interface RunnableVersion extends Version {
state: VersionState;
source: VersionSource;
downloadProgress?: number;
}
export interface SetFiddleOptions {
filePath?: string;
templateName?: string;
gistId?: string;
}
export interface OutputEntry {
text: string;
timestamp: number;
}
isNotPre?: boolean;
}
export interface OutputOptions {
bypassBuffer?: boolean;
isNotPre?: boolean;
}
export interface GenericDialogOptions {
type: GenericDialogType;
ok?: string;
cancel?: string;
wantsInput?: boolean;
label: string | JSX.Element;
placeholder?: string;
}
export interface Templates {
[index: string]: string | Templates;
}
export const enum GenericDialogType {
'confirm' = 'confirm',
'warning' = 'warning',
'success' = 'success',
}
// Editors
export const enum EditorId {
'main' = 'main',
'renderer' = 'renderer',
'html' = 'html',
'preload' = 'preload',
'css' = 'css',
}
// Panels that can show up as a mosaic
export const enum PanelId {
'docsDemo' = 'docsDemo',
}
export type MosaicId = EditorId | PanelId;
export const ALL_EDITORS = [
EditorId.main,
EditorId.renderer,
EditorId.preload,
EditorId.html,
EditorId.css,
];
export const ALL_PANELS = [PanelId.docsDemo];
export const ALL_MOSAICS = [...ALL_EDITORS, ...ALL_PANELS];
export type ArrowPosition = 'top' | 'left' | 'bottom' | 'right';
export const enum DocsDemoPage {
DEFAULT = 'DEFAULT',
DEMO_APP = 'DEMO_APP',
}
+69
View File
@@ -0,0 +1,69 @@
export enum IpcEvents {
OPEN_SETTINGS = 'OPEN_SETTINGS',
LOAD_GIST_REQUEST = 'LOAD_GIST_REQUEST',
LOAD_ELECTRON_EXAMPLE_REQUEST = 'LOAD_ELECTRON_EXAMPLE_REQUEST',
FIDDLE_RUN = 'FIDDLE_RUN',
FIDDLE_PACKAGE = 'FIDDLE_PACKAGE',
FIDDLE_MAKE = 'FIDDLE_MAKE',
MONACO_EXECUTE_COMMAND = 'MONACO_EXECUTE_COMMAND',
MONACO_TOGGLE_OPTION = 'MONACO_TOGGLE_OPTION',
FS_NEW_FIDDLE = 'FS_NEW_FIDDLE',
FS_OPEN_FIDDLE = 'FS_OPEN_FIDDLE',
FS_OPEN_TEMPLATE = 'FS_OPEN_TEMPLATE',
FS_SAVE_FIDDLE = 'FS_SAVE_FIDDLE',
FS_SAVE_FIDDLE_AS = 'FS_SAVE_FIDDLE_AS',
FS_SAVE_FIDDLE_GIST = 'FS_SAVE_FIDDLE_GIST',
FS_SAVE_FIDDLE_FORGE = 'FS_SAVE_FIDDLE_FORGE',
FS_SAVE_FIDDLE_DIALOG = 'FS_SAVE_FIDDLE_DIALOG',
FS_SAVE_FIDDLE_ERROR = 'FS_SAVE_FIDDLE_ERROR',
SHOW_WARNING_DIALOG = 'SHOW_WARNING_DIALOG',
SHOW_CONFIRMATION_DIALOG = 'SHOW_CONFIRMATION_DIALOG',
SHOW_WELCOME_TOUR = 'SHOW_WELCOME_TOUR',
CLEAR_CONSOLE = 'CLEAR_CONSOLE',
LOAD_LOCAL_VERSION_FOLDER = 'LOAD_LOCAL_VERSION_FOLDER',
SHOW_LOCAL_VERSION_FOLDER_DIALOG = 'SHOW_LOCAL_VERSION_FOLDER_DIALOG',
BISECT_COMMANDS_TOGGLE = 'BISECT_COMMANDS_TOGGLE',
SHOW_INACTIVE = 'SHOW_INACTIVE',
BEFORE_QUIT = 'BEFORE_QUIT',
CONFIRM_QUIT = 'CONFIRM_QUIT',
SET_APPDATA_DIR = 'SET_APPDATA_DIR',
SELECT_ALL_IN_EDITOR = 'SELECT_ALL_IN_EDITOR',
}
export const ipcMainEvents = [
IpcEvents.FS_SAVE_FIDDLE_DIALOG,
IpcEvents.FS_SAVE_FIDDLE,
IpcEvents.SHOW_WARNING_DIALOG,
IpcEvents.SHOW_CONFIRMATION_DIALOG,
IpcEvents.SHOW_LOCAL_VERSION_FOLDER_DIALOG,
IpcEvents.SHOW_INACTIVE,
IpcEvents.CONFIRM_QUIT,
];
export const ipcRendererEvents = [
IpcEvents.OPEN_SETTINGS,
IpcEvents.LOAD_GIST_REQUEST,
IpcEvents.LOAD_ELECTRON_EXAMPLE_REQUEST,
IpcEvents.FIDDLE_RUN,
IpcEvents.FIDDLE_PACKAGE,
IpcEvents.FIDDLE_MAKE,
IpcEvents.MONACO_EXECUTE_COMMAND,
IpcEvents.MONACO_TOGGLE_OPTION,
IpcEvents.FS_NEW_FIDDLE,
IpcEvents.FS_OPEN_FIDDLE,
IpcEvents.FS_OPEN_TEMPLATE,
IpcEvents.FS_SAVE_FIDDLE,
IpcEvents.FS_SAVE_FIDDLE_AS,
IpcEvents.FS_SAVE_FIDDLE_FORGE,
IpcEvents.FS_SAVE_FIDDLE_GIST,
IpcEvents.SHOW_WELCOME_TOUR,
IpcEvents.CLEAR_CONSOLE,
IpcEvents.LOAD_LOCAL_VERSION_FOLDER,
IpcEvents.BISECT_COMMANDS_TOGGLE,
IpcEvents.BEFORE_QUIT,
IpcEvents.SET_APPDATA_DIR,
IpcEvents.SELECT_ALL_IN_EDITOR,
];
export const WEBCONTENTS_READY_FOR_IPC_SIGNAL =
'WEBCONTENTS_READY_FOR_IPC_SIGNAL';
+45
View File
@@ -0,0 +1,45 @@
@import (inline) "../../node_modules/@blueprintjs/core/lib/css/blueprint.css";
@import (inline) "../../node_modules/@blueprintjs/select/lib/css/blueprint-select.css";
@import (inline) "../../node_modules/@blueprintjs/icons/lib/css/blueprint-icons.css";
@import (inline) "../../node_modules/@blueprintjs/core/lib/less/variables.less";
// Override some of the colors
.fiddle.bp3-dark {
.bp3-menu,
.bp3-popover .bp3-popover-content {
background-color: @background-1;
}
.bp3-popover .bp3-popover-arrow-fill {
fill: @background-1;
}
.bp3-button:not([class*="bp3-intent-"]) {
background-color: @background-1;
}
.bp3-button.bp3-minimal {
background-color: unset;
}
.bp3-button:hover,
.bp3-button.bp3-minimal:hover {
background-color: rgba(138, 155, 168, 0.15);
}
.bp3-menu-item.bp3-active.bp3-intent-primary {
background-color: @foreground-3;
}
.bp3-dialog {
background-color: @background-4;
.bp3-dialog-header {
background-color: @background-3;
}
}
.bp3-running-text {
font-size: 14px;
}
}
+17
View File
@@ -0,0 +1,17 @@
.darwin {
.chrome {
text-align: center;
background-color: @background-1;
border-bottom: @border;
-webkit-app-region: drag;
height: 24px;
font-size: 1.4rem;
line-height: 15px;
small,
p,
span {
user-select: none;
}
}
}
+73
View File
@@ -0,0 +1,73 @@
@import "../variables.less";
header {
box-shadow: 0 0 0 1px rgba(16, 22, 26, 0.2), 0 0 0 rgba(16, 22, 26, 0), 0 1px 1px rgba(16, 22, 26, 0.4);
background-color: @background-3;
-webkit-app-region: drag;
}
.commands {
display: flex;
justify-content: space-between;
height: 50px;
padding: 10px;
box-sizing: border-box;
font-family: @fonts-common;
button,
input,
select {
-webkit-app-region: no-drag;
margin-bottom: 0;
white-space: nowrap;
}
select {
width: 100px;
margin-left: 5px;
}
fieldset {
border: 0;
padding: 0;
margin: 0;
min-width: 0;
}
& > div {
display: flex;
&:last-of-type {
margin-right: 10px;
.bp3-button-group {
margin-left: 5px;
}
}
}
.bp3-control-group {
margin-right: 0.5rem;
}
.address-bar {
width: 420px;
transition: width 0.4s;
input,
span {
-webkit-app-region: no-drag;
}
&.empty {
width: 300px;
}
&:focus-within {
span,
input {
border-color: @foreground-2;
}
}
}
}
+213
View File
@@ -0,0 +1,213 @@
@import "../variables.less";
.dialogs {
z-index: 10;
position: fixed;
height: 100vh;
width: 100vw;
pointer-events: none;
* {
pointer-events: all;
}
}
.darwin {
.dialogs {
padding-top: 23px;
}
}
.dialog {
background-color: @background-3;
border: @border;
color: @text-color-1;
border-radius: 6px;
padding: 10px;
z-index: 100;
display: flex;
flex-direction: column;
justify-content: space-between;
animation: slide-up 0.4s ease;
p {
margin-bottom: 1.25rem;
font-size: 1.25rem;
}
code {
font-size: 12px;
background: rgba(255, 255, 255, 0.1);
padding: 2px;
line-height: 12px;
}
&-buttons {
margin-top: 1.25rem;
}
&.centered {
position: absolute;
width: 300px;
left: calc(50% - (300px / 2));
top: 100px;
}
&.arrow::after,
&.arrow::before {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
&.arrow::after {
border-color: rgba(136, 183, 213, 0);
border-width: 9px;
}
&.arrow::before {
border-color: rgba(194, 225, 245, 0);
border-width: 10px;
}
&.arrow-top::after,
&.arrow-top::before {
bottom: 100%;
left: 50%;
}
&.arrow-top::after {
border-bottom-color: @background-3;
margin-left: -9px;
}
&.arrow-top::before {
border-bottom-color: @border-color-1;
margin-left: -10px;
}
&.arrow-bottom::after,
&.arrow-bottom::before {
top: 100%;
left: 50%;
}
&.arrow-bottom::after {
border-top-color: @background-3;
margin-left: -9px;
}
&.arrow-bottom::before {
border-top-color: @border-color-1;
margin-left: -10px;
}
&.arrow-left::after,
&.arrow-left::before {
right: 100%;
top: 20px;
}
&.arrow-left::after {
border-right-color: @background-3;
margin-top: -9px;
}
&.arrow-left::before {
border-right-color: @border-color-1;
margin-top: -10px;
}
&.arrow-right::after,
&.arrow-right::before {
left: 100%;
top: 20px;
}
&.arrow-right::after {
border-left-color: @background-3;
margin-top: -9px;
}
&.arrow-right::before {
border-left-color: @border-color-1;
margin-top: -10px;
}
button {
color: #1e2527;
float: right;
margin-left: 9px;
margin-bottom: 0;
}
a {
cursor: pointer;
}
h4 {
margin-bottom: 0;
}
p:last-of-type {
margin-bottom: 0;
}
input {
color: rgba(159, 234, 249, 0.5);
height: 28px;
margin-top: 10px;
background-color: @background-1;
border: 1px solid @border-color-2;
outline: 0 solid transparent;
&:focus {
border-color: @foreground-2;
}
}
}
.dialogDrop {
position: fixed;
z-index: 100;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: black;
transition: opacity 0.4s ease-in-out;
pointer-events: all;
opacity: 0.5;
}
.dialog-add-version {
.bp3-file-input {
width: 100%;
}
.bp3-callout {
margin-top: 1rem;
}
}
select {
font-size: 12px;
height: 28px;
background-color: white;
line-height: 15px;
}
@keyframes slide-up {
0% {
opacity: 0;
transform: translateY(20px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
+45
View File
@@ -0,0 +1,45 @@
.mosaic-tile {
animation: fadein 0.15s;
}
.mosaic-window-toolbar {
& > div {
display: flex;
justify-content: space-between;
width: 100%;
padding: 0 5px 0 5px;
.mosaic-controls {
transform: scale(0.75);
transform-origin: right;
}
h5 {
margin: 4px 0 0 0;
}
button {
margin-left: 8px;
}
}
}
// update if list of Editor ID changes
@editor-ids: main, renderer, html, preload;
// takes each editor ID and increase its z-index if the parent Mosiac root
// has focused__id class for that specific id.
each(@editor-ids, {
.focused__@{value}.mosaic .mosaic-window.@{value} {
z-index: 2;
}
});
.mosaic-window {
z-index: 1;
}
@keyframes fadein {
from { opacity: 0; }
to { opacity: 1; }
}
+59
View File
@@ -0,0 +1,59 @@
@import "../variables.less";
.fiddle {
.mosaic-window-toolbar {
background: var(--background-1);
box-shadow: inset 0 0 100px 100px rgba(53, 53, 53, 0.1);
border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.mosaic-window-toolbar.draggable:hover {
box-shadow: inset 0 0 100px 100px rgba(255, 255, 255, 0.1);
}
.mosaic-window-title {
color: var(--text-color-3);
}
button.mosaic-default-control {
padding: 0;
height: 20px;
width: 20px;
margin: 5px;
background-color: #314246;
border: 0.1rem solid #222b35;
}
button.mosaic-default-control:hover {
background-color: #131d1f;
}
.mosaic-window-body {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: stretch;
align-content: stretch;
overflow: visible;
z-index: 4;
background-color: @background-4;
}
.mosaic {
height: 100vh;
&.mosaic-blueprint-theme {
background: #bdbdbd15;
}
}
.editorContainer,
.monaco-editor {
width: 100%;
height: 100%;
}
.editorContainer {
background: @background-1;
}
}
+25
View File
@@ -0,0 +1,25 @@
@import "../variables.less";
.output {
font-size: 12px;
font-family: @fonts-common;
font-weight: 600;
color: var(--text-color-1);
background: var(--background-2);
box-shadow: inset 0 0 100px 100px rgba(0, 0, 0, 0.15);
border-top: @border;
top: 10vh;
padding: 0;
padding-top: 10px;
padding-left: 10px;
height: 100%;
overflow-y: scroll;
-webkit-app-region: no-drag;
p {
margin-bottom: 0;
white-space: pre;
padding-left: 5.6em;
text-indent: -5.6em;
}
}
+189
View File
@@ -0,0 +1,189 @@
@import "../variables.less";
.settings {
background: @background-3;
z-index: 10;
position: absolute;
height: 100%;
width: 100vw;
display: flex;
user-select: none;
cursor: initial;
a:hover {
cursor: pointer;
}
h1,
h2,
h3,
h4,
h5 {
color: @text-color-1;
cursor: initial;
}
h4 {
margin-bottom: 5px;
}
label {
font-weight: 200;
}
select {
width: 250px;
}
.bp3-divider {
margin-top: 1rem;
margin-bottom: 1rem;
margin-left: 0;
margin-right: 0;
}
.bp3-callout {
max-width: 850px;
}
.electron-versions-table {
width: 100%;
.action {
text-align: right;
}
}
.settings-content {
height: 100%;
width: 100%;
padding: 20px;
overflow: scroll;
color: @text-color-3;
box-sizing: border-box;
}
.settings-electron {
.advanced-options-buttons {
display: flex;
flex-flow: row wrap;
> div {
margin-right: 1rem;
button {
width: 100%;
}
}
> div:last-of-type {
margin-right: 0;
}
}
.versions-to-show {
margin-bottom: 2rem;
border-bottom: 1px solid @border-color-1;
padding-bottom: 1.5rem;
p {
margin-bottom: 1rem;
}
label {
display: inline;
margin-right: 10px;
}
}
}
.settings-section {
margin-bottom: 20px;
&:last-of-type {
margin: 0;
}
}
.settings-close {
position: fixed;
right: 30px;
height: 25px;
width: 25px;
text-align: center;
cursor: pointer;
border-radius: 15px;
color: var(--text-color-3);
&:hover {
color: @text-color-1;
}
svg {
background: @background-3;
box-shadow: 0 0 12px 6px @background-3;
}
}
.contributors {
display: flex;
flex-wrap: wrap;
.contributor {
width: 320px;
height: 120px;
background: rgba(255, 255, 255, 0.1);
padding: 10px;
margin: 0 10px 10px 0;
display: flex;
justify-content: flex-start;
cursor: pointer;
&:hover {
background: rgba(255, 255, 255, 0.15);
}
h5,
p {
margin-bottom: 0;
}
.avatar {
height: 100px;
width: 100px;
background-size: contain;
margin-right: 10px;
}
.details {
max-width: 190px;
overflow: scroll;
}
}
}
.settings-menu {
height: 100%;
width: 250px;
background-color: @background-1;
user-select: none;
ul {
list-style: none;
padding: 20px;
}
li {
font-size: 1rem;
padding-top: 10px;
padding-bottom: 10px;
border-bottom: @border;
color: var(--text-color-1);
opacity: 0.8;
&:hover {
opacity: 1;
}
}
}
}
+21
View File
@@ -0,0 +1,21 @@
.show-me-panel {
padding: 10px;
overflow: scroll;
& > *:first-child {
margin-top: 0;
};
.bp3-callout {
margin-bottom: 10px;
}
}
.show-me-list {
display: flex;
flex-direction: column;
flex-wrap: wrap;
list-style: none;
padding: 0;
max-height: 400px;
}
+12
View File
@@ -0,0 +1,12 @@
.tour {
position: fixed;
top: 0;
left: 0;
height: 100vh;
width: 100vw;
z-index: 200;
}
.tour-portal {
z-index: 1000;
}
+5
View File
@@ -0,0 +1,5 @@
.bp3-fill {
.version-chooser {
width: 100%;
}
}
+9
View File
@@ -0,0 +1,9 @@
.container {
display: flex;
flex-direction: column;
height: 100vh;
width: 100vw;
margin: 0;
padding: 0;
max-width: unset;
}
+85
View File
@@ -0,0 +1,85 @@
body {
padding: 0;
margin: 0;
background: @background-1;
overflow: hidden;
display: flex;
flex-direction: column;
height: 100vh;
*:focus {
outline: none;
}
}
.fiddle {
*::-webkit-scrollbar {
width: 14px;
}
*::-webkit-scrollbar-track {
background: unset;
}
*::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.4);
}
*::-webkit-scrollbar-corner {
background: unset;
}
.drag {
-webkit-app-region: drag;
}
.shadow {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
.timestamp {
margin-right: 5px;
color: var(--text-color-1);
opacity: 0.7;
user-select: none;
}
}
#editors {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: stretch;
align-content: stretch;
height: 100%;
}
.editor {
flex-grow: 1;
width: 30%;
}
.resize {
width: 6px;
background: rgba(0, 0, 0, 0.2);
margin-left: 9px;
margin-right: 0;
cursor: col-resize;
flex-grow: 0;
flex-shrink: 0;
}
#runner {
height: 0;
}
#runner:not(:empty) {
height: 200px;
}
.editorTitle span {
width: 33%;
display: inline-block;
text-align: center;
font-size: 12px;
}
+334
View File
@@ -0,0 +1,334 @@
/*
* The CSS below is a modified version of the original, increasing the
* FPS from ~11 during scrolling to 60 by reducing the number of
* style calculations.
*/
/**
* @license
* Copyright 2016 Palantir Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.mosaic {
height: 100%;
width: 100%;
}
.mosaic,
.mosaic > * {
box-sizing: border-box;
}
.mosaic .mosaic-zero-state {
width: auto;
height: auto;
max-width: none;
z-index: 1;
}
.mosaic .mosaic-zero-state .pt-non-ideal-state-icon .pt-icon {
font-size: 120px;
}
.mosaic-root {
position: absolute;
top: 3px;
right: 3px;
bottom: 3px;
left: 3px;
}
.mosaic-split {
position: absolute;
z-index: 1;
}
.mosaic-split:hover {
background: black;
}
.mosaic-split .mosaic-split-line {
position: absolute;
}
.mosaic-split.-row {
margin-left: -3px;
width: 6px;
cursor: ew-resize;
}
.mosaic-split.-row .mosaic-split-line {
top: 0;
bottom: 0;
left: 3px;
right: 3px;
}
.mosaic-split.-column {
margin-top: -3px;
height: 6px;
cursor: ns-resize;
}
.mosaic-split.-column .mosaic-split-line {
top: 3px;
bottom: 3px;
left: 0;
right: 0;
}
.mosaic-tile {
position: absolute;
margin: 3px;
}
.mosaic-tile > * {
height: 100%;
width: 100%;
}
.mosaic-drop-target {
position: relative;
}
.mosaic-drop-target.drop-target-hover .drop-target-container {
display: block;
}
.mosaic-drop-target.mosaic > .drop-target-container .drop-target.left {
right: calc(100% - 10px );
}
.mosaic-drop-target.mosaic > .drop-target-container .drop-target.right {
left: calc(100% - 10px );
}
.mosaic-drop-target.mosaic > .drop-target-container .drop-target.bottom {
top: calc(100% - 10px );
}
.mosaic-drop-target.mosaic > .drop-target-container .drop-target.top {
bottom: calc(100% - 10px );
}
.mosaic-drop-target .drop-target-container {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: none;
}
.mosaic-drop-target .drop-target-container.-dragging {
display: block;
}
.mosaic-drop-target .drop-target-container .drop-target {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgba(0, 0, 0, 0.2);
border: 2px solid black;
opacity: 0;
z-index: 5;
}
.mosaic-drop-target .drop-target-container .drop-target.left {
right: calc(100% - 30% );
}
.mosaic-drop-target .drop-target-container .drop-target.right {
left: calc(100% - 30% );
}
.mosaic-drop-target .drop-target-container .drop-target.bottom {
top: calc(100% - 30% );
}
.mosaic-drop-target .drop-target-container .drop-target.top {
bottom: calc(100% - 30% );
}
.mosaic-drop-target .drop-target-container .drop-target.drop-target-hover {
opacity: 1;
}
.mosaic-drop-target .drop-target-container .drop-target.drop-target-hover.left {
right: calc(100% - 50% );
}
.mosaic-drop-target .drop-target-container .drop-target.drop-target-hover.right {
left: calc(100% - 50% );
}
.mosaic-drop-target .drop-target-container .drop-target.drop-target-hover.bottom {
top: calc(100% - 50% );
}
.mosaic-drop-target .drop-target-container .drop-target.drop-target-hover.top {
bottom: calc(100% - 50% );
}
.mosaic-window,
.mosaic-preview {
position: relative;
display: flex;
flex-direction: column;
box-shadow: 0 0 1px rgba(0, 0, 0, 0.2);
}
.mosaic-window .mosaic-window-toolbar,
.mosaic-preview .mosaic-window-toolbar {
z-index: 4;
display: flex;
justify-content: space-between;
align-items: center;
flex-shrink: 0;
height: 30px;
background: white;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
}
.mosaic-window .mosaic-window-toolbar.draggable,
.mosaic-preview .mosaic-window-toolbar.draggable {
cursor: move;
}
.mosaic-window .mosaic-window-title,
.mosaic-preview .mosaic-window-title {
padding-left: 15px;
flex: 1;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
min-height: 18px;
}
.mosaic-window .mosaic-window-controls,
.mosaic-preview .mosaic-window-controls {
display: flex;
height: 100%;
}
.mosaic-window .mosaic-window-controls .separator,
.mosaic-preview .mosaic-window-controls .separator {
height: 20px;
border-left: 1px solid black;
margin: 5px 4px;
}
.mosaic-window .mosaic-window-body,
.mosaic-preview .mosaic-window-body {
position: relative;
flex: 1;
height: 0;
background: white;
z-index: 1;
overflow: hidden;
}
.mosaic-window .mosaic-window-additional-actions-bar,
.mosaic-preview .mosaic-window-additional-actions-bar {
position: absolute;
top: 30px;
right: 0;
bottom: initial;
left: 0;
height: 0;
overflow: hidden;
background: white;
justify-content: flex-end;
display: flex;
z-index: 3;
}
.mosaic-window .mosaic-window-additional-actions-bar .pt-button,
.mosaic-preview .mosaic-window-additional-actions-bar .pt-button {
margin: 0;
}
.mosaic-window .mosaic-window-additional-actions-bar .pt-button::after,
.mosaic-preview .mosaic-window-additional-actions-bar .pt-button::after {
display: none;
}
.mosaic-window .mosaic-window-body-overlay,
.mosaic-preview .mosaic-window-body-overlay {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
opacity: 0;
background: white;
display: none;
z-index: 2;
}
.mosaic-window.additional-controls-open .mosaic-window-additional-actions-bar,
.mosaic-preview.additional-controls-open .mosaic-window-additional-actions-bar {
height: 30px;
}
.mosaic-window.additional-controls-open .mosaic-window-body-overlay,
.mosaic-preview.additional-controls-open .mosaic-window-body-overlay {
display: block;
}
.mosaic-window .mosaic-preview,
.mosaic-preview .mosaic-preview {
height: 100%;
width: 100%;
position: absolute;
z-index: 0;
border: 1px solid black;
max-height: 400px;
}
.mosaic-window .mosaic-preview .mosaic-window-body,
.mosaic-preview .mosaic-preview .mosaic-window-body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.mosaic-window .mosaic-preview h4,
.mosaic-preview .mosaic-preview h4 {
margin-bottom: 10px;
}
.mosaic-window .mosaic-preview .pt-icon,
.mosaic-preview .mosaic-preview .pt-icon {
font-size: 72px;
}
.mosaic:not(.mosaic-blueprint-theme) .mosaic-default-control.pt-icon-cross::before {
content: 'Close';
}
.mosaic:not(.mosaic-blueprint-theme) .mosaic-default-control.pt-icon-add-column-right::before {
content: 'Split';
}
.mosaic:not(.mosaic-blueprint-theme) .mosaic-default-control.pt-icon-exchange::before {
content: 'Replace';
}
.mosaic:not(.mosaic-blueprint-theme) .mosaic-default-control.pt-icon-maximize::before {
content: 'Expand';
}
+20
View File
@@ -0,0 +1,20 @@
// Blueprint
@import "blueprint.less";
// Variables, also imported in each file
@import "variables.less";
@import "main.less";
@import "container.less";
@import "mosaic-vendor.less";
// Components
@import "components/commands.less";
@import "components/output.less";
@import "components/dialogs.less";
@import "components/mosaic.less";
@import "components/settings.less";
@import "components/chrome-mac.less";
@import "components/editors.less";
@import "components/tour.less";
@import "components/show-me.less";
@import "components/version-select.less";
+25
View File
@@ -0,0 +1,25 @@
// We'll take these values from the theme.
// Colors
@foreground-1: var(--foreground-1);
@foreground-2: var(--foreground-2);
@foreground-3: var(--foreground-3);
@background-4: var(--background-4);
@background-3: var(--background-3);
@background-2: var(--background-2);
@background-1: var(--background-1);
@border-color-2: var(--border-color-2);
@border-color-1: var(--border-color-1);
@border: var(--border);
@text-color-1: var(--text-color-1);
@text-color-2: var(--text-color-2);
@text-color-3: var(--text-color-3);
// Dynamically created
@button-text-color: var(--button-text-color);
// Fonts
@fonts-common: var(--fonts-common);
// Lengths
@header-height: 50px;
-60
View File
@@ -1,60 +0,0 @@
require('update-electron-app')();
const { app, BrowserWindow } = require('electron');
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) { // eslint-disable-line global-require
app.quit();
}
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;
const createWindow = () => {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 1200,
height: 900,
titleBarStyle: 'hiddenInset',
acceptFirstMouse: true
});
// and load the index.html of the app.
mainWindow.loadFile('./static/index.html');
// Open the DevTools.
// mainWindow.webContents.openDevTools();
// Emitted when the window is closed.
mainWindow.on('closed', () => {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null;
});
};
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow();
}
});
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and import them here.
+29
View File
@@ -0,0 +1,29 @@
import { AboutPanelOptionsOptions, app } from 'electron';
/**
* Sets Fiddle's About panel options on Linux and macOS
*
* @returns
*/
export function setupAboutPanel(): void {
if (process.platform === 'win32') return;
const options: AboutPanelOptionsOptions = {
applicationName: 'Electron Fiddle',
applicationVersion: app.getVersion(),
version: process.versions.electron,
copyright: '© Electron Authors',
};
switch (process.platform) {
case 'linux':
options.website = 'https://electronjs.org/fiddle';
case 'darwin':
options.credits =
'https://github.com/electron/fiddle/graphs/contributors';
default:
// fallthrough
}
app.setAboutPanelOptions(options);
}
+177
View File
@@ -0,0 +1,177 @@
import {
BrowserWindow,
ContextMenuParams,
Menu,
MenuItemConstructorOptions,
} from 'electron';
import { IpcEvents } from '../ipc-events';
import { isDevMode } from '../utils/devmode';
import { ipcMainManager } from './ipc';
/**
* Returns items related to running the current fiddle.
*
* @returns {Array<MenuItemConstructorOptions>}
*/
export function getRunItems(): Array<MenuItemConstructorOptions> {
return [
{
id: 'run',
label: 'Run Fiddle',
click: () => ipcMainManager.send(IpcEvents.FIDDLE_RUN),
},
{
id: 'clear_console',
label: 'Clear Console',
click: () => ipcMainManager.send(IpcEvents.CLEAR_CONSOLE),
},
{
type: 'separator',
},
];
}
/**
* Possibly returns items interacting with the Monaco editor.
* Our check for "are we in the Monaco editor" is pretty crude -
* we just assume that we are if we can paste text.
*
* @param {BrowserWindow} browserWindow
* @param {ContextMenuParams} { x, y }
* @returns {Array<MenuItemConstructorOptions>}
*/
export function getMonacoItems({
pageURL,
editFlags,
}: ContextMenuParams): Array<MenuItemConstructorOptions> {
if (!editFlags.canPaste || !/.*index\.html(#?)$/.test(pageURL || '')) {
return [];
}
return [
{
id: 'go_to_definition',
label: 'Go to Definition',
click() {
const cmd = ['editor.action.goToDeclaration'];
ipcMainManager.send(IpcEvents.MONACO_EXECUTE_COMMAND, cmd);
},
},
{
id: 'peek_definition',
label: 'Peek Definition',
click() {
const cmd = ['editor.action.previewDeclaration'];
ipcMainManager.send(IpcEvents.MONACO_EXECUTE_COMMAND, cmd);
},
},
{
id: 'references',
label: 'Find References',
click() {
const cmd = ['editor.action.referenceSearch.trigger'];
ipcMainManager.send(IpcEvents.MONACO_EXECUTE_COMMAND, cmd);
},
},
{ type: 'separator' },
{
id: 'palette',
label: 'Command Palette',
click() {
const cmd = ['editor.action.quickCommand'];
ipcMainManager.send(IpcEvents.MONACO_EXECUTE_COMMAND, cmd);
},
},
{ type: 'separator' },
{
id: 'format_document',
label: 'Format Document',
click() {
const cmd = ['editor.action.formatDocument'];
ipcMainManager.send(IpcEvents.MONACO_EXECUTE_COMMAND, cmd);
},
},
{
id: 'format_selection',
label: 'Format Selection',
click() {
const cmd = ['editor.action.formatSelection'];
ipcMainManager.send(IpcEvents.MONACO_EXECUTE_COMMAND, cmd);
},
},
{ type: 'separator' },
];
}
/**
* Possibly returns the `Inspect Element` item.
*
* @param {BrowserWindow} browserWindow
* @param {ContextMenuParams} { x, y }
* @returns {Array<MenuItemConstructorOptions>}
*/
export function getInspectItems(
browserWindow: BrowserWindow,
{ x, y }: ContextMenuParams,
): Array<MenuItemConstructorOptions> {
if (!isDevMode()) return [];
return [
{
id: 'inspect',
label: 'Inspect Element',
click: () => {
browserWindow.webContents.inspectElement(x, y);
try {
if (browserWindow.webContents.isDevToolsOpened()) {
browserWindow.webContents.devToolsWebContents?.focus();
}
} catch (error) {
console.warn(`Tried to focus dev tools, but failed`, { error });
}
},
},
];
}
/**
* Creates a context menu for a given BrowserWindow
*
* @param {BrowserWindow} browserWindow
*/
export function createContextMenu(browserWindow: BrowserWindow) {
browserWindow.webContents.on('context-menu', (_event, props) => {
const { editFlags } = props;
const template: Array<MenuItemConstructorOptions> = [
...getRunItems(),
...getMonacoItems(props),
{
id: 'cut',
label: 'Cut',
role: 'cut',
enabled: editFlags.canCut,
},
{
id: 'copy',
label: 'Copy',
role: 'copy',
enabled: editFlags.canCopy,
},
{
id: 'paste',
label: 'Paste',
role: 'paste',
enabled: editFlags.canPaste,
},
{
type: 'separator',
},
...getInspectItems(browserWindow, props),
];
const menu = Menu.buildFromTemplate(template);
menu.popup({});
});
}
+27
View File
@@ -0,0 +1,27 @@
import { isDevMode } from '../utils/devmode';
/**
* Installs developer tools if we're in dev mode.
*
* @export
* @returns {Promise<void>}
*/
export async function setupDevTools(): Promise<void> {
if (!isDevMode()) return;
const {
default: installExtension,
REACT_DEVELOPER_TOOLS,
REACT_PERF,
} = require('electron-devtools-installer');
try {
const react = await installExtension(REACT_DEVELOPER_TOOLS);
console.log(`installDevTools: Installed ${react}`);
const perf = await installExtension(REACT_PERF);
console.log(`installDevTools: Installed ${perf}`);
} catch (error) {
console.warn(`installDevTools: Error occured:`, error);
}
}
+63
View File
@@ -0,0 +1,63 @@
import { dialog, IpcMainEvent } from 'electron';
import { IpcEvents } from '../ipc-events';
import { ipcMainManager } from './ipc';
import { getOrCreateMainWindow } from './windows';
/**
* Listens to IPC events related to dialogs and message boxes
*
* @export
*/
export function setupDialogs() {
ipcMainManager.on(IpcEvents.SHOW_WARNING_DIALOG, (_event, args) => {
showWarningDialog(args);
});
ipcMainManager.on(IpcEvents.SHOW_CONFIRMATION_DIALOG, (_event, args) => {
showConfirmationDialog(args);
});
ipcMainManager.on(
IpcEvents.SHOW_LOCAL_VERSION_FOLDER_DIALOG,
async (event) => {
await showOpenDialog(event);
},
);
}
/**
* Shows a warning dialog
*
* @param {Electron.MessageBoxOptions} args
*/
function showWarningDialog(args: Electron.MessageBoxOptions) {
dialog.showMessageBox(getOrCreateMainWindow(), {
type: 'warning',
...args,
});
}
/**
* Shows a confirmation dialog
*
* @param {Electron.MessageBoxOptions} args
*/
function showConfirmationDialog(args: Electron.MessageBoxOptions) {
dialog.showMessageBox(getOrCreateMainWindow(), {
type: 'warning',
...args,
});
}
async function showOpenDialog(event: IpcMainEvent) {
const { filePaths } = await dialog.showOpenDialog({
title: 'Open Folder',
properties: ['openDirectory'],
});
if (!filePaths || filePaths.length < 1) {
return;
}
event.reply(IpcEvents.LOAD_LOCAL_VERSION_FOLDER, [filePaths[0]]);
}
+110
View File
@@ -0,0 +1,110 @@
import { dialog } from 'electron';
import * as fs from 'fs-extra';
import * as path from 'path';
import { IpcEvents } from '../ipc-events';
import {
INDEX_HTML_NAME,
MAIN_JS_NAME,
PACKAGE_NAME,
RENDERER_JS_NAME,
} from '../shared-constants';
import { ipcMainManager } from './ipc';
/**
* Ensures that we're listening to file events
*/
export function setupFileListeners() {
ipcMainManager.on(IpcEvents.FS_SAVE_FIDDLE_DIALOG, () => {
showSaveDialog();
});
}
/**
* Shows the "Open Fiddle" dialog and forwards
* the path to the renderer
*/
export async function showOpenDialog() {
const { filePaths } = await dialog.showOpenDialog({
title: 'Open Fiddle',
properties: ['openDirectory'],
});
if (!filePaths || filePaths.length < 1) {
return;
}
ipcMainManager.send(IpcEvents.FS_OPEN_FIDDLE, [filePaths[0]]);
}
/**
* Shows the "Save Fiddle" dialog and forwards
* the path to the renderer
*/
export async function showSaveDialog(event?: IpcEvents, as?: string) {
// We want to save to a folder, so we'll use an open dialog here
const { filePaths } = await dialog.showOpenDialog({
buttonLabel: 'Save here',
properties: ['openDirectory', 'createDirectory'],
title: `Save Fiddle${as ? ` as ${as}` : ''}`,
});
if (!filePaths || filePaths.length < 1) {
return;
}
console.log(`Asked to save to ${filePaths[0]}`);
// Let's confirm real quick if we want this
if (await ensureSaveTargetEmpty(filePaths[0])) {
ipcMainManager.send(event || IpcEvents.FS_SAVE_FIDDLE, [filePaths[0]]);
}
}
/**
* Ensures that a folder designated for saving is empty
*
* @param {string} filePath
* @returns {Promise<boolean>}
*/
async function ensureSaveTargetEmpty(filePath: string): Promise<boolean> {
const targetPaths = [
path.join(filePath, INDEX_HTML_NAME),
path.join(filePath, RENDERER_JS_NAME),
path.join(filePath, MAIN_JS_NAME),
path.join(filePath, PACKAGE_NAME),
];
let noFilesOrOverwriteGranted = true;
for (const targetPath of targetPaths) {
if (fs.existsSync(targetPath) && noFilesOrOverwriteGranted) {
noFilesOrOverwriteGranted = await confirmFileOverwrite(targetPath);
}
}
return noFilesOrOverwriteGranted;
}
/**
* Pops open a confirmation dialog, asking the user if they really
* want to overwrite an existing file
*
* @param {string} filePath
* @returns {Promise<boolean>}
*/
async function confirmFileOverwrite(filePath: string): Promise<boolean> {
try {
const result = await dialog.showMessageBox({
type: 'warning',
buttons: ['Cancel', 'Yes'],
message: 'Overwrite files?',
detail: `The file ${filePath} already exists. Do you want to overwrite it?`,
});
return !!result;
} catch (error) {
// Let's not overwrite files. We'd rather crash.
throw error;
}
}
+34
View File
@@ -0,0 +1,34 @@
import { app, dialog } from 'electron';
import { isFirstRun } from '../utils/check-first-run';
import { isDevMode } from '../utils/devmode';
/**
* Is this the first run of Fiddle? If so, perform
* tasks that we only want to do in this case.
*/
export async function onFirstRunMaybe() {
if (isFirstRun()) {
await promptMoveToApplicationsFolder();
}
}
/**
* Ask the user if the app should be moved to the
* applications folder.
*/
async function promptMoveToApplicationsFolder(): Promise<void> {
if (process.platform !== 'darwin') return;
if (isDevMode() || app.isInApplicationsFolder()) return;
const { response } = await dialog.showMessageBox({
type: 'question',
buttons: ['Move to Applications Folder', 'Do Not Move'],
defaultId: 0,
message: 'Move to Applications Folder?',
});
if (response === 0) {
app.moveToApplicationsFolder();
}
}
+74
View File
@@ -0,0 +1,74 @@
import { ipcMain } from 'electron';
import { EventEmitter } from 'events';
import {
IpcEvents,
ipcMainEvents,
WEBCONTENTS_READY_FOR_IPC_SIGNAL,
} from '../ipc-events';
import { getOrCreateMainWindow } from './windows';
/**
* The main purpose of this class is to be the central
* gathering place for IPC calls the main process sends
* or listens to.
*
* @class IpcManager
* @extends {EventEmitter}
*/
export class IpcMainManager extends EventEmitter {
public readyWebContents = new WeakSet<Electron.WebContents>();
private messageQueue = new WeakMap<
Electron.WebContents,
Array<[IpcEvents, Array<any> | undefined]>
>();
constructor() {
super();
ipcMainEvents.forEach((name) => {
ipcMain.removeAllListeners(name);
ipcMain.on(name, (...args: Array<any>) => this.emit(name, ...args));
});
ipcMain.on(
WEBCONTENTS_READY_FOR_IPC_SIGNAL,
(event: Electron.IpcMainEvent) => {
this.readyWebContents.add(event.sender);
const queue = this.messageQueue.get(event.sender);
this.messageQueue.delete(event.sender);
if (!queue) return;
for (const item of queue) {
this.send(item[0], item[1], event.sender);
}
},
);
}
/**
* Send an IPC message to an instance of Electron.WebContents.
* If none is specified, we'll automatically go with the main window.
*
* @param {IpcEvents} channel
* @param {Array<any>} args
* @param {Electron.WebContents} [target]
*/
public send(
channel: IpcEvents,
args?: Array<any>,
target?: Electron.WebContents,
) {
const _target = target || getOrCreateMainWindow().webContents;
const _args = args || [];
if (!this.readyWebContents.has(_target)) {
const existing = this.messageQueue.get(_target) || [];
this.messageQueue.set(_target, [...existing, [channel, args]]);
return;
}
_target.send(channel, ..._args);
}
}
export const ipcMainManager = new IpcMainManager();
+98
View File
@@ -0,0 +1,98 @@
import { initSentry } from '../sentry';
initSentry();
import { app } from 'electron';
import { IpcEvents } from '../ipc-events';
import { isDevMode } from '../utils/devmode';
import { setupAboutPanel } from './about-panel';
import { setupDevTools } from './devtools';
import { setupDialogs } from './dialogs';
import { onFirstRunMaybe } from './first-run';
import { ipcMainManager } from './ipc';
import { listenForProtocolHandler, setupProtocolHandler } from './protocol';
import { shouldQuit } from './squirrel';
import { setupUpdates } from './update';
import { getOrCreateMainWindow } from './windows';
/**
* Handle the app's "ready" event. This is essentially
* the method that takes care of booting the application.
*/
export async function onReady() {
await onFirstRunMaybe();
if (!isDevMode()) process.env.NODE_ENV = 'production';
getOrCreateMainWindow();
setupAboutPanel();
const { setupMenu } = await import('./menu');
const { setupFileListeners } = await import('./files');
setupMenu();
setupProtocolHandler();
setupFileListeners();
setupUpdates();
setupDialogs();
setupDevTools();
}
/**
* Handle the "before-quit" event
*
* @export
*/
export function onBeforeQuit() {
ipcMainManager.send(IpcEvents.BEFORE_QUIT);
ipcMainManager.on(IpcEvents.CONFIRM_QUIT, quitAppIfConfirmed);
}
export function quitAppIfConfirmed(
_: Electron.IpcMainEvent,
quitConfirmed: boolean,
) {
if (quitConfirmed) {
app.quit();
}
}
/**
* All windows have been closed, quit on anything but
* macOS.
*/
export function onWindowsAllClosed() {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit();
}
}
/**
* The main method - and the first function to run
* when Fiddle is launched.
*
* Exported for testing purposes.
*/
export function main() {
// Handle creating/removing shortcuts on Windows when
// installing/uninstalling.
if (shouldQuit()) {
app.quit();
return;
}
// Set the app's name
app.name = 'Electron Fiddle';
// Ensure that there's only ever one Fiddle running
listenForProtocolHandler();
// Launch
app.whenReady().then(onReady);
app.on('before-quit', onBeforeQuit);
app.on('window-all-closed', onWindowsAllClosed);
app.on('activate', getOrCreateMainWindow);
}
main();
+337
View File
@@ -0,0 +1,337 @@
import {
app,
BrowserWindow,
Menu,
MenuItemConstructorOptions,
shell,
} from 'electron';
import { Templates } from '../interfaces';
import { IpcEvents } from '../ipc-events';
import { SHOW_ME_TEMPLATES } from '../templates';
import { showOpenDialog, showSaveDialog } from './files';
import { ipcMainManager } from './ipc';
import { createMainWindow } from './windows';
/**
* Is the passed object a constructor for an Electron Menu?
*
* @param {(Array<Electron.MenuItemConstructorOptions> | Electron.Menu)} [submenu]
* @returns {submenu is Array<Electron.MenuItemConstructorOptions>}
*/
function isSubmenu(
submenu?: Array<MenuItemConstructorOptions> | Menu,
): submenu is Array<MenuItemConstructorOptions> {
return !!submenu && Array.isArray(submenu);
}
/**
* Returns additional items for the help menu
*
* @returns {Array<Electron.MenuItemConstructorOptions>}
*/
function getHelpItems(): Array<MenuItemConstructorOptions> {
return [
{
type: 'separator',
},
{
label: 'Show Welcome Tour',
click() {
ipcMainManager.send(IpcEvents.SHOW_WELCOME_TOUR);
},
},
{
type: 'separator',
},
{
label: 'Toggle Developer Tools',
accelerator: 'CmdOrCtrl+Option+i',
click() {
const browserWindow = BrowserWindow.getFocusedWindow();
if (browserWindow && !browserWindow.isDestroyed()) {
browserWindow.webContents.toggleDevTools();
}
},
},
{
type: 'separator',
},
{
label: 'Open Fiddle Repository...',
click() {
shell.openExternal('https://github.com/electron/fiddle');
},
},
{
label: 'Open Electron Repository...',
click() {
shell.openExternal('https://github.com/electron/electron');
},
},
{
label: 'Open Electron Issue Tracker...',
click() {
shell.openExternal('https://github.com/electron/electron/issues');
},
},
];
}
/**
* Depending on the OS, the `Preferences` either go into the `Fiddle`
* menu (macOS) or under `File` (Linux, Windows)
*
* @returns {Array<Electron.MenuItemConstructorOptions>}
*/
function getPreferencesItems(): Array<MenuItemConstructorOptions> {
return [
{
type: 'separator',
},
{
label: 'Preferences',
accelerator: 'CmdOrCtrl+,',
click() {
ipcMainManager.send(IpcEvents.OPEN_SETTINGS);
},
},
{
type: 'separator',
},
];
}
/**
* Returns the Exit items
*
* @returns {Array<Electron.MenuItemConstructorOptions>}
*/
function getQuitItems(): Array<MenuItemConstructorOptions> {
return [
{
type: 'separator',
},
{
role: 'quit',
},
];
}
/**
* Returns the top-level "File" menu
*
* @returns {Array<Electron.MenuItemConstructorOptions>}
*/
function getTasksMenu(): MenuItemConstructorOptions {
const tasksMenu: Array<MenuItemConstructorOptions> = [
{
label: 'Run Fiddle...',
accelerator: 'F5',
click: () => ipcMainManager.send(IpcEvents.FIDDLE_RUN),
},
{
label: 'Package Fiddle...',
click: () => ipcMainManager.send(IpcEvents.FIDDLE_PACKAGE),
},
{
label: 'Make installers for Fiddle...',
click: () => ipcMainManager.send(IpcEvents.FIDDLE_MAKE),
},
];
return {
label: 'Tasks',
submenu: tasksMenu,
};
}
function getShowMeMenuItem(
key: string,
item: string | Templates,
): MenuItemConstructorOptions {
if (typeof item === 'string') {
return {
label: key,
click: () => ipcMainManager.send(IpcEvents.FS_OPEN_TEMPLATE, [key]),
};
}
return {
label: key,
submenu: Object.keys(item).map((subkey) => {
return getShowMeMenuItem(subkey, item[subkey]);
}),
};
}
function getShowMeMenu(): MenuItemConstructorOptions {
const showMeMenu: Array<MenuItemConstructorOptions> = Object.keys(
SHOW_ME_TEMPLATES,
).map((key) => getShowMeMenuItem(key, SHOW_ME_TEMPLATES[key]));
return {
label: 'Show Me',
submenu: showMeMenu,
};
}
/**
* Returns the top-level "File" menu
*
* @returns {Array<Electron.MenuItemConstructorOptions>}
*/
function getFileMenu(): MenuItemConstructorOptions {
const fileMenu: Array<MenuItemConstructorOptions> = [
{
label: 'New Fiddle',
click: () => ipcMainManager.send(IpcEvents.FS_NEW_FIDDLE),
accelerator: 'CmdOrCtrl+N',
},
{
label: 'New Window',
click: () => createMainWindow(),
accelerator: 'CmdOrCtrl+Shift+N',
},
{
type: 'separator',
},
{
label: 'Open',
click: showOpenDialog,
accelerator: 'CmdOrCtrl+O',
},
{
type: 'separator',
},
{
label: 'Save',
click: () => ipcMainManager.send(IpcEvents.FS_SAVE_FIDDLE),
accelerator: 'CmdOrCtrl+S',
},
{
label: 'Save as',
click: () => showSaveDialog(IpcEvents.FS_SAVE_FIDDLE),
accelerator: 'CmdOrCtrl+Shift+S',
},
{
type: 'separator',
},
{
label: 'Publish to Gist',
click: () => ipcMainManager.send(IpcEvents.FS_SAVE_FIDDLE_GIST),
},
{
label: 'Save as Forge Project',
click: () =>
showSaveDialog(IpcEvents.FS_SAVE_FIDDLE_FORGE, 'Forge Project'),
},
];
// macOS has these items in the "Fiddle" menu
if (process.platform !== 'darwin') {
fileMenu.splice(
fileMenu.length,
0,
...getPreferencesItems(),
...getQuitItems(),
);
}
return {
label: 'File',
submenu: fileMenu,
};
}
/**
* Creates the app's window menu.
*/
export function setupMenu() {
// Get template for default menu
const defaultMenu = require('electron-default-menu');
const menu = (defaultMenu(app, shell) as Array<
MenuItemConstructorOptions
>).map((item) => {
const { label } = item;
// Append the "Settings" item
if (
process.platform === 'darwin' &&
label === app.name &&
isSubmenu(item.submenu)
) {
item.submenu.splice(2, 0, ...getPreferencesItems());
}
// Custom handler for "Select All" for Monaco
if (label === 'Edit' && isSubmenu(item.submenu)) {
const selectAll = item.submenu.find((i) => i.label === 'Select All')!;
delete selectAll.role; // override default role
selectAll.click = () => {
ipcMainManager.send(IpcEvents.SELECT_ALL_IN_EDITOR);
// Allow selection to occur in text fields outside the editors.
if (process.platform === 'darwin') {
Menu.sendActionToFirstResponder('selectAll:');
}
};
}
// Tweak "View" menu
if (label === 'View' && isSubmenu(item.submenu)) {
// remove "Reload" (has weird behaviour) and "Toggle Developer Tools"
item.submenu = item.submenu.filter(
(subItem) =>
subItem.label !== 'Toggle Developer Tools' &&
subItem.label !== 'Reload',
);
item.submenu.push(
{ type: 'separator' },
{ role: 'resetZoom' },
{ role: 'zoomIn' },
{ role: 'zoomOut' },
); // Add zooming actions
item.submenu.push(
{ type: 'separator' },
{
label: 'Toggle Soft Wrap',
click: () =>
ipcMainManager.send(IpcEvents.MONACO_TOGGLE_OPTION, ['wordWrap']),
},
);
item.submenu.push(
{ type: 'separator' },
{
label: 'Toggle Mini Map',
click: () =>
ipcMainManager.send(IpcEvents.MONACO_TOGGLE_OPTION, [
'minimap.enabled',
]),
},
);
item.submenu.push(
{ type: 'separator' },
{
label: 'Toggle Bisect Helper',
click: () => ipcMainManager.send(IpcEvents.BISECT_COMMANDS_TOGGLE),
accelerator: 'CommandorControl+Shift+B',
},
);
}
// Append items to "Help"
if (label === 'Help' && isSubmenu(item.submenu)) {
item.submenu = getHelpItems();
}
return item;
});
menu.splice(process.platform === 'darwin' ? 1 : 0, 0, getFileMenu());
menu.splice(menu.length - 1, 0, getTasksMenu(), getShowMeMenu());
Menu.setApplicationMenu(Menu.buildFromTemplate(menu));
}
+109
View File
@@ -0,0 +1,109 @@
import { app } from 'electron';
import * as fs from 'fs';
import * as path from 'path';
import * as nodeUrl from 'url';
import { IpcEvents } from '../ipc-events';
import { isDevMode } from '../utils/devmode';
import { ipcMainManager } from './ipc';
const PROTOCOL = 'electron-fiddle';
const squirrelPath = path.resolve(
path.dirname(process.execPath),
'..',
'electron-fiddle.exe',
);
const handlePotentialProtocolLaunch = (url: string) => {
if (!app.isReady()) {
app.once('ready', () => handlePotentialProtocolLaunch(url));
return;
}
const parsed = nodeUrl.parse(url.replace(/\/$/, ''));
if (!parsed.pathname || !parsed.hostname) return;
const pathParts = parsed.pathname.split('/').slice(1);
switch (parsed.hostname) {
// electron-fiddle://gist/blub
case 'gist':
if (pathParts.length === 1) {
// We only have a gist ID
ipcMainManager.send(IpcEvents.LOAD_GIST_REQUEST, [
{
id: pathParts[0],
},
]);
} else if (pathParts.length === 2) {
// We have a gist owner and gist ID, we can ignore the owner
ipcMainManager.send(IpcEvents.LOAD_GIST_REQUEST, [
{
id: pathParts[1],
},
]);
} else {
// This is a super invalid gist launch
return;
}
break;
// electron-fiddle://electron/{ref}/{path}
case 'electron':
if (pathParts.length > 1) {
// First part of the commit HASH / ref / branch
// Rest is the path to the example
ipcMainManager.send(IpcEvents.LOAD_ELECTRON_EXAMPLE_REQUEST, [
{
ref: pathParts[0],
path: pathParts.slice(1).join('/'),
},
]);
} else {
// This is an invalid electron launch
return;
}
break;
default:
return;
}
};
export const scanArgv = (argv: Array<string>) => {
const protocolArg = argv.find((arg) => arg.startsWith(`${PROTOCOL}://`));
if (protocolArg) {
console.info('Found protocol arg in argv:', protocolArg);
handlePotentialProtocolLaunch(protocolArg);
}
};
export const scanNpmArgv = (argv: string) => {
const parsedArgv = JSON.parse(argv);
const { original: args } = parsedArgv;
scanArgv(args);
};
export const listenForProtocolHandler = () => {
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) app.quit();
app.removeAllListeners('open-url');
app.on('open-url', (_, url) => {
if (url.startsWith(`${PROTOCOL}://`)) {
handlePotentialProtocolLaunch(url);
}
});
// pass protocol URL via npm start args in dev mode
if (isDevMode() && process.env.npm_config_argv) {
scanNpmArgv(process.env.npm_config_argv);
} else if (process.platform === 'win32') {
scanArgv(process.argv);
}
};
export const setupProtocolHandler = () => {
if (process.platform === 'win32' && !fs.existsSync(squirrelPath)) return;
if (!app.isDefaultProtocolClient(PROTOCOL, squirrelPath)) {
app.setAsDefaultProtocolClient(PROTOCOL, squirrelPath);
}
};
+3
View File
@@ -0,0 +1,3 @@
export function shouldQuit() {
return require('electron-squirrel-startup');
}
+15
View File
@@ -0,0 +1,15 @@
/**
* Sets up the update service
*/
export function setupUpdates() {
// We delay this work by 10s to ensure that the
// app doesn't have to worry about updating during launch
setTimeout(() => {
const updateApp = require('update-electron-app');
updateApp({
repo: 'electron/fiddle',
updateInterval: '1 hour',
});
}, 10000);
}
+94
View File
@@ -0,0 +1,94 @@
import { app, BrowserWindow, shell } from 'electron';
import { IpcEvents } from '../ipc-events';
import { createContextMenu } from './context-menu';
import { ipcMainManager } from './ipc';
// Keep a global reference of the window objects, if we don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
export let browserWindows: Array<BrowserWindow | null> = [];
/**
* Gets default options for the main window
*
* @returns {Electron.BrowserWindowConstructorOptions}
*/
export function getMainWindowOptions(): Electron.BrowserWindowConstructorOptions {
return {
width: 1200,
height: 900,
minHeight: 600,
minWidth: 600,
titleBarStyle: process.platform === 'darwin' ? 'hidden' : undefined,
acceptFirstMouse: true,
backgroundColor: '#1d2427',
webPreferences: {
webviewTag: false,
nodeIntegration: true,
},
};
}
/**
* Creates a new main window.
*
* @export
* @returns {Electron.BrowserWindow}
*/
export function createMainWindow(): Electron.BrowserWindow {
console.log(`Creating main window`);
let browserWindow: BrowserWindow | null;
browserWindow = new BrowserWindow(getMainWindowOptions());
browserWindow.loadFile('./dist/static/index.html');
browserWindow.webContents.once('dom-ready', () => {
if (browserWindow) {
browserWindow.show();
createContextMenu(browserWindow);
}
});
browserWindow.on('closed', () => {
browserWindows = browserWindows.filter((bw) => browserWindow !== bw);
browserWindow = null;
});
browserWindow.webContents.on('new-window', (event, url) => {
event.preventDefault();
shell.openExternal(url);
});
browserWindow.webContents.on('will-navigate', (event, url) => {
event.preventDefault();
shell.openExternal(url);
});
ipcMainManager.on(IpcEvents.SHOW_INACTIVE, () => {
if (browserWindow) {
browserWindow.showInactive();
}
});
const appData = app.getPath('appData');
ipcMainManager.send(
IpcEvents.SET_APPDATA_DIR,
[appData],
browserWindow.webContents,
);
browserWindows.push(browserWindow);
return browserWindow;
}
/**
* Gets or creates the main window, returning it in both cases.
*
* @returns {Electron.BrowserWindow}
*/
export function getOrCreateMainWindow(): Electron.BrowserWindow {
return (
BrowserWindow.getFocusedWindow() || browserWindows[0] || createMainWindow()
);
}
+214 -81
View File
@@ -1,96 +1,229 @@
import * as React from 'react';
import { render } from 'react-dom';
import * as loader from 'monaco-loader';
import { observable } from 'mobx';
import { initSentry } from '../sentry';
initSentry();
import { mainTheme } from './themes';
import { getContent } from './content';
import { Header } from './components/header';
import { BinaryManager } from './binary';
import { ElectronVersion, StringMap, OutputEntry } from '../interfaces';
import { arrayToStringMap } from '../utils/array-to-stringmap';
import { getKnownVersions } from './versions';
import { normalizeVersion } from '../utils/normalize-version';
import { when } from 'mobx';
import * as MonacoType from 'monaco-editor';
const knownVersions = getKnownVersions();
const defaultVersion = normalizeVersion(knownVersions[0].tag_name);
import { ipcRenderer } from 'electron';
import {
ALL_EDITORS,
EditorId,
EditorValues,
GenericDialogType,
SetFiddleOptions,
} from '../interfaces';
import { WEBCONTENTS_READY_FOR_IPC_SIGNAL } from '../ipc-events';
import { updateEditorLayout } from '../utils/editor-layout';
import { getEditorValue } from '../utils/editor-value';
import { getPackageJson, PackageJsonOptions } from '../utils/get-package';
import { getTitle } from '../utils/get-title';
import { isEditorBackup } from '../utils/type-checks';
import { EMPTY_EDITOR_CONTENT } from './constants';
import { FileManager } from './file-manager';
import { RemoteLoader } from './remote-loader';
import { Runner } from './runner';
import { appState } from './state';
import { getTheme } from './themes';
import { TouchBarManager } from './touch-bar-manager';
export class AppState {
@observable public version: string = defaultVersion;
@observable public binaryManager: BinaryManager = new BinaryManager(defaultVersion);
@observable public versions: StringMap<ElectronVersion> = arrayToStringMap(knownVersions);
@observable public output: Array<OutputEntry> = [];
@observable public isConsoleShowing: boolean = false;
}
const appState = new AppState();
class App {
public editors: any = {
main: null,
renderer: null,
html: null
};
public monaco: any = null;
public name = 'test';
/**
* The top-level class controlling the whole app. This is *not* a React component,
* but it does eventually render all components.
*
* @class App
*/
export class App {
public typeDefDisposable: MonacoType.IDisposable | null = null;
public monaco: typeof MonacoType | null = null;
public state = appState;
public fileManager = new FileManager(appState);
public remoteLoader = new RemoteLoader(appState);
public runner = new Runner(appState);
public touchBarManager: TouchBarManager | undefined;
constructor() {
this.getValues = this.getValues.bind(this);
this.getEditorValues = this.getEditorValues.bind(this);
this.setEditorValues = this.setEditorValues.bind(this);
this.setup();
if (process.platform === 'darwin') {
this.touchBarManager = new TouchBarManager(appState);
}
}
private async setup() {
this.monaco = await loader();
public async replaceFiddle(
editorValues: Partial<EditorValues>,
{ filePath, gistId, templateName }: Partial<SetFiddleOptions>,
) {
// if unsaved, prompt user to make sure they're okay with overwriting and changing directory
if (this.state.isUnsaved) {
this.state.setGenericDialogOptions({
type: GenericDialogType.warning,
label: `Opening this Fiddle will replace your unsaved changes. Do you want to proceed?`,
ok: 'Yes',
});
this.state.isGenericDialogShowing = true;
await when(() => !this.state.isGenericDialogShowing);
this.createThemes();
this.editors.html = this.createEditor('html');
this.editors.main = this.createEditor('main');
this.editors.renderer = this.createEditor('renderer');
render(<Header appState={appState} />, document.getElementById('header'));
}
private createThemes() {
this.monaco.editor.defineTheme('main', mainTheme);
}
private createEditor(id: string) {
if (!this.monaco) throw new Error('Monaco not ready');
const element = document.getElementById(`editor-${id}`);
const language = id === 'html' ? 'html' : 'javascript';
const value = getContent(id);
const options = {
language,
theme: 'main',
automaticLayout: true,
minimap: {
enabled: false
},
value
};
return this.monaco.editor.create(element, options);
}
private getValues() {
if (!this.editors.html || !this.editors.main || !this.editors.renderer) {
throw new Error('Editors not ready');
if (!this.state.genericDialogLastResult) {
return false;
}
}
return {
html: this.editors.html!.getValue(),
main: this.editors.main!.getValue(),
renderer: this.editors.renderer!.getValue(),
package: JSON.stringify({
name: this.name,
main: './main.js',
version: '1.0.0'
})
// display all editors that have content
const visibleEditors = [];
for (const id of Object.keys(editorValues)) {
const content = editorValues[id];
// if the gist content matches the empty file output, don't show it
if (!Object.values(EMPTY_EDITOR_CONTENT).includes(content)) {
visibleEditors.push(id as EditorId);
}
}
this.state.gistId = gistId || '';
this.state.localPath = filePath;
this.state.templateName = templateName;
// once loaded, we have a "saved" state
await this.state.setVisibleMosaics(visibleEditors);
await this.setEditorValues(editorValues);
this.state.isUnsaved = false;
document.title = getTitle(this.state);
return true;
}
/**
* Sets the contents of all editor panes.
*
* @param {EditorValues} values
*/
public async setEditorValues(values: Partial<EditorValues>): Promise<void> {
const { ElectronFiddle: fiddle } = window;
if (!fiddle) {
throw new Error('Fiddle not ready');
}
for (const name of ALL_EDITORS) {
const editor = fiddle.editors[name];
const backup = this.state.closedPanels[name];
if (typeof values[name] !== 'undefined') {
if (isEditorBackup(backup)) {
// The editor does not exist, attempt to set it on the backup.
// If there's a model, we'll do it on the model. Else, we'll
// set the value.
if (backup.model) {
backup.model.setValue(values[name]!);
} else {
backup.value = values[name]!;
}
} else if (editor && editor.setValue) {
// The editor exists, set the value directly
editor.setValue(values[name]!);
}
}
}
}
/**
* Retrieves the contents of all editor panes.
*
* @returns {EditorValues}
*/
public async getEditorValues(
options?: PackageJsonOptions,
): Promise<EditorValues> {
const { ElectronFiddle: fiddle } = window;
if (!fiddle) {
throw new Error('Fiddle not ready');
}
const values: EditorValues = {
css: getEditorValue(EditorId.css),
html: getEditorValue(EditorId.html),
main: getEditorValue(EditorId.main),
preload: getEditorValue(EditorId.preload),
renderer: getEditorValue(EditorId.renderer),
};
if (options && options.include !== false) {
values.package = await getPackageJson(this.state, values, options);
}
return values;
}
/**
* Initial setup call, loading Monaco and kicking off the React
* render process.
*/
public async setup(): Promise<void | Element | React.Component> {
this.setupTheme();
const React = await import('react');
const { render } = await import('react-dom');
const { Dialogs } = await import('./components/dialogs');
const { OutputEditorsWrapper } = await import(
'./components/output-editors-wrapper'
);
const { Header } = await import('./components/header');
const className = `${process.platform} container`;
const app = (
<div className={className}>
<Dialogs appState={this.state} />
<Header appState={this.state} />
<OutputEditorsWrapper appState={this.state} />
</div>
);
const rendered = render(app, document.getElementById('app'));
this.setupResizeListener();
ipcRenderer.send(WEBCONTENTS_READY_FOR_IPC_SIGNAL);
return rendered;
}
/**
* Loads theme CSS into the HTML document.
*
* @returns {Promise<void>}
*/
public async setupTheme(): Promise<void> {
const tag: HTMLStyleElement | null = document.querySelector(
'style#fiddle-theme',
);
const theme = await getTheme(this.state.theme);
if (tag && theme.css) {
tag.innerHTML = theme.css;
}
if (theme.isDark || theme.name.includes('dark')) {
document.body.classList.add('bp3-dark');
} else {
document.body.classList.remove('bp3-dark');
}
}
/**
* We need to possibly recalculate the layout whenever the window
* is resized. This method sets up the listener.
*/
public setupResizeListener(): void {
window.addEventListener('resize', updateEditorLayout);
}
}
(window as any).electronFiddle = new App();
window.ElectronFiddle = window.ElectronFiddle || {};
window.ElectronFiddle.contentChangeListeners =
window.ElectronFiddle.contentChangeListeners || [];
window.ElectronFiddle.app = window.ElectronFiddle.app || new App();
window.ElectronFiddle.app.setup();
+251 -91
View File
@@ -1,115 +1,275 @@
import { promisify } from 'util';
import * as os from 'os';
import * as fs from 'fs-extra';
import * as fsType from 'fs-extra';
import * as path from 'path';
import * as extract from 'extract-zip';
import { EventEmitter } from 'events';
import { userData } from './constants';
import { VersionState } from '../interfaces';
import { fancyImport } from '../utils/import';
import { normalizeVersion } from '../utils/normalize-version';
import { StringMap } from '../interfaces';
import { USER_DATA_PATH } from './constants';
import { removeTypeDefsForVersion } from './fetch-types';
import { AppState } from './state';
const eDownload = promisify(require('electron-download'));
/**
* General setup, called with a version. Is called during construction
* to ensure that we always have or download at least one version.
*
* @param {string} iVersion
* @returns {Promise<void>}
*/
export async function setupBinary(
appState: AppState,
iVersion: string,
): Promise<void> {
const version = normalizeVersion(iVersion);
const fs = await fancyImport<typeof fsType>('fs-extra');
export class BinaryManager extends EventEmitter {
public state: StringMap<'ready' | 'downloading'> = {};
public version: string = '2.0.2';
await fs.mkdirp(getDownloadPath(version));
constructor(version: string) {
super();
this.setup(version);
const { state } = appState.versions[version];
if (state === VersionState.downloading || state === VersionState.unzipping) {
console.log(`Binary: Electron ${version} already downloading.`);
return;
}
public async setup(iVersion: string) {
const version = normalizeVersion(iVersion);
await fs.mkdirp(this.getDownloadPath(version));
if (this.state[version] === 'downloading') {
console.log(`BinaryManager: Electron ${version} already downloading.`);
return;
}
if (this.getIsDownloaded(version)) {
console.log(`BinaryManager: Electron ${version} already downloaded.`);
this.state[version] = 'ready';
return;
}
console.log(`BinaryManager: Electron ${version} not present, downloading`);
this.state[version] = 'downloading';
const zipPath = await eDownload({ version });
const extractPath = this.getDownloadPath(version);
console.log(`BinaryManager: Electron ${version} downloaded, now unpacking`);
const electronFiles = await this.unzip(zipPath, extractPath);
console.log(electronFiles);
this.state[version] = 'ready';
if (await getIsDownloaded(version)) {
console.log(`Binary: Electron ${version} already downloaded.`);
appState.versions[version].state = VersionState.ready;
return;
}
public getElectronBinary(version: string) {
const platform = os.platform();
const dir = this.getDownloadPath(version);
console.log(`Binary: Electron ${version} not present, downloading`);
appState.versions[version].state = VersionState.downloading;
switch (platform) {
case 'darwin':
return path.join(dir, 'Electron.app/Contents/MacOS/Electron');
case 'freebsd':
case 'linux':
return path.join(dir, 'electron');
case 'win32':
return path.join(dir, 'electron.exe');
default:
throw new Error('Electron builds are not available on platform: ' + platform);
}
const zipPath = await download(appState, version);
const extractPath = getDownloadPath(version);
console.log(
`Binary: Electron ${version} downloaded, now unpacking to ${extractPath}`,
);
try {
appState.versions[version].state = VersionState.unzipping;
// Ensure the target path is empty
await fs.emptyDir(extractPath);
const electronFiles = await unzip(zipPath, extractPath);
console.log(`Unzipped ${version}`, electronFiles);
} catch (error) {
console.warn(`Failure while unzipping ${version}`, error);
appState.versions[version].state = VersionState.unknown;
return;
}
public async getDownloadedVersions(): Promise<Array<string>> {
const downloadPath = path.join(userData, 'electron-bin');
console.log(`BinaryManager: Checking for downloaded versions`);
appState.versions[version].state = VersionState.ready;
}
/**
* Remove a version from disk. Does not update state. We'll try up to
* four times before giving up if an error occurs.
*
* @param {string} iVersion
* @returns {Promise<void>}
*/
export async function removeBinary(iVersion: string) {
const version = normalizeVersion(iVersion);
const fs = await fancyImport<typeof fsType>('fs-extra');
let isDeleted = false;
// utility to re-run removal functions upon failure
// due to windows filesystem lockfile jank
const rerunner = async (func: () => Promise<void>, counter = 1) => {
try {
const directories = await fs.readdir(downloadPath);
const knownVersions: Array<string> = [];
for (const directory of directories) {
if (this.getIsDownloaded(directory)) {
knownVersions.push(directory);
}
}
return knownVersions;
await func();
} catch (error) {
console.warn(`Could not read known Electron versions`);
return [];
console.warn(
`Binary Manager: failed to run ${func.name} for ${version}, but failed`,
error,
);
if (counter < 4) {
console.log(`Binary Manager: Trying again to run ${func.name}`);
await rerunner(func, counter + 1);
}
}
}
};
public getIsDownloaded(version: string) {
const expectedPath = this.getElectronBinary(version);
return fs.existsSync(expectedPath);
}
private getDownloadPath(version: string) {
return path.join(userData, 'electron-bin', version);
}
private unzip(zipPath: string, extractPath: string) {
return new Promise((resolve, reject) => {
const binaryCleaner = async () => {
if (await getIsDownloaded(version)) {
// This is necessary since we're messing with .asar files inside
// the Electron binaries. Electron, powering Fiddle, will try to
// "correct" our calls, but we don't want that right here.
process.noAsar = true;
await fs.remove(getDownloadPath(version));
process.noAsar = false;
extract(zipPath, { dir: extractPath }, (error) => {
if (error) {
reject(error);
return;
}
isDeleted = true;
}
};
console.log(`BinaryManager: Unpacked!`);
process.noAsar = false;
const typeDefsCleaner = async () => {
await removeTypeDefsForVersion(version);
};
resolve();
});
});
await rerunner(binaryCleaner);
if (isDeleted) {
await rerunner(typeDefsCleaner);
}
}
/* Did we already download a given version?
*
* @param {string} version
* @param {string} dir
* @returns {boolean}
*/
export async function getIsDownloaded(
version: string,
dir?: string,
): Promise<boolean> {
const expectedPath = getElectronBinaryPath(version, dir);
const fs = await fancyImport<typeof fsType>('fs-extra');
return fs.existsSync(expectedPath);
}
/**
* Gets the expected path for the binary of a given Electron version
*
* @param {string} version
* @param {string} dir
* @returns {string}
*/
export function getElectronBinaryPath(
version: string,
dir: string = getDownloadPath(version),
): string {
switch (process.platform) {
case 'darwin':
return path.join(dir, 'Electron.app/Contents/MacOS/Electron');
case 'freebsd':
case 'linux':
return path.join(dir, 'electron');
case 'win32':
return path.join(dir, 'electron.exe');
default:
throw new Error(
`Electron builds are not available for ${process.platform}`,
);
}
}
export function getDownloadingVersions(appState: AppState) {
return Object.entries(appState.versions)
.filter(([_, { state }]) => state === 'downloading')
.map(([version, _]) => version);
}
/**
* Returns an array of all versions downloaded to disk
*
* @returns {Promise<Array<string>>}
*/
export async function getDownloadedVersions(): Promise<Array<string>> {
const fs = await fancyImport<typeof fsType>('fs-extra');
const downloadPath = path.join(USER_DATA_PATH, 'electron-bin');
console.log(`Binary: Checking for downloaded versions`);
try {
const directories = await fs.readdir(downloadPath);
const knownVersions: Array<string> = [];
for (const directory of directories) {
if (await getIsDownloaded(directory)) {
knownVersions.push(directory);
}
}
return knownVersions;
} catch (error) {
console.warn(`Could not read known Electron versions`);
return [];
}
}
/**
* Download an Electron version.
*
* @param {AppState} appState
* @param {string} version
* @returns {Promise<string>}
*/
async function download(appState: AppState, version: string): Promise<string> {
const { download: electronDownload } = await import('@electron/get');
const getProgressCallback = (progress: Progress) => {
const roundedProgress = Math.round(progress.percent * 100) / 100;
if (roundedProgress !== appState.versions[version].downloadProgress) {
console.debug(
`Binary: Version ${version} download progress: ${progress.percent}`,
);
appState.versions[version].downloadProgress = roundedProgress;
}
};
if (!appState.versions[version]) {
throw new Error(
`Version ${version} does not exist in state, cannot download`,
);
}
const zipFilePath = await electronDownload(version, {
downloadOptions: {
quiet: true,
getProgressCallback,
},
});
return zipFilePath;
}
/**
* Gets the expected path for a given Electron version
*
* @param {string} version
* @returns {string}
*/
function getDownloadPath(version: string): string {
return path.join(USER_DATA_PATH, 'electron-bin', version);
}
/**
* Unzips an electron package so that we can actually use it.
*
* @param {string} zipPath
* @param {string} extractPath
* @returns {Promise<void>}
*/
function unzip(zipPath: string, extractPath: string): Promise<void> {
return new Promise(async (resolve, reject) => {
const extract = (await fancyImport<any>('extract-zip')).default;
process.noAsar = true;
const options = {
dir: extractPath,
};
extract(zipPath, options, (error: Error) => {
if (error) {
reject(error);
return;
}
console.log(`Binary: Unpacked!`);
process.noAsar = false;
resolve();
});
});
}
interface Progress {
percent: number;
transferred: number;
total: number;
}
+59
View File
@@ -0,0 +1,59 @@
import { RunnableVersion } from '../interfaces';
export class Bisector {
public revList: Array<RunnableVersion>;
public minRev: number;
public maxRev: number;
private pivot: number;
constructor(revList: Array<RunnableVersion>) {
this.getCurrentVersion = this.getCurrentVersion.bind(this);
this.continue = this.continue.bind(this);
this.calculatePivot = this.calculatePivot.bind(this);
this.revList = revList;
this.minRev = 0;
this.maxRev = revList.length - 1;
this.calculatePivot();
}
public getCurrentVersion() {
return this.revList[this.pivot];
}
public continue(isGoodVersion: boolean) {
let isBisectOver = false;
if (this.maxRev - this.minRev <= 1) {
isBisectOver = true;
}
if (isGoodVersion) {
const upPivot = Math.floor((this.maxRev - this.pivot) / 2) + this.pivot;
this.minRev = this.pivot;
if (upPivot !== this.maxRev && upPivot !== this.pivot) {
this.pivot = upPivot;
} else {
isBisectOver = true;
}
} else {
const downPivot =
Math.floor((this.pivot - this.minRev) / 2) + this.minRev;
this.maxRev = this.pivot;
if (downPivot !== this.minRev && downPivot !== this.pivot) {
this.pivot = downPivot;
} else {
isBisectOver = true;
}
}
if (isBisectOver) {
return [this.revList[this.minRev], this.revList[this.maxRev]];
} else {
return this.revList[this.pivot];
}
}
private calculatePivot() {
this.pivot = Math.floor((this.maxRev - this.minRev) / 2);
}
}
+40
View File
@@ -0,0 +1,40 @@
import { remote } from 'electron';
import { observer } from 'mobx-react';
import * as React from 'react';
import { getTitle } from '../../utils/get-title';
import { AppState } from '../state';
export interface ChromeMacProps {
appState: AppState;
}
@observer
export class ChromeMac extends React.Component<ChromeMacProps> {
public handleDoubleClick = () => {
const doubleClickAction = remote.systemPreferences.getUserDefault(
'AppleActionOnDoubleClick',
'string',
);
const win = remote.getCurrentWindow();
if (doubleClickAction === 'Minimize') {
win.minimize();
} else if (doubleClickAction === 'Maximize') {
if (!win.isMaximized()) {
win.maximize();
} else {
win.unmaximize();
}
}
};
public render() {
if (process.platform !== 'darwin') return null;
return (
<div className="chrome drag" onDoubleClick={this.handleDoubleClick}>
<small>{getTitle(this.props.appState)}</small>
</div>
);
}
}
@@ -0,0 +1,440 @@
import {
Button,
ButtonGroup,
IToastProps,
Menu,
MenuItem,
Popover,
Position,
Toaster,
} from '@blueprintjs/core';
import { observer } from 'mobx-react';
import * as React from 'react';
import { when } from 'mobx';
import {
EditorValues,
GenericDialogType,
GistActionState,
GistActionType,
} from '../../interfaces';
import { IpcEvents } from '../../ipc-events';
import {
INDEX_HTML_NAME,
MAIN_JS_NAME,
PRELOAD_JS_NAME,
RENDERER_JS_NAME,
STYLES_CSS_NAME,
} from '../../shared-constants';
import { getOctokit } from '../../utils/octokit';
import { EMPTY_EDITOR_CONTENT } from '../constants';
import { ipcRendererManager } from '../ipc';
import { AppState } from '../state';
export interface GistActionButtonProps {
appState: AppState;
}
interface IGistActionButtonState {
readonly isUpdating: boolean;
readonly isDeleting: boolean;
readonly actionType: GistActionType;
}
/**
* The "publish" button takes care of logging you in.
*
* @export
* @class GistActionButton
* @extends {React.Component<GistActionButtonProps, GistActionButtonState>}
*/
@observer
export class GistActionButton extends React.Component<
GistActionButtonProps,
IGistActionButtonState
> {
public constructor(props: GistActionButtonProps) {
super(props);
this.handleClick = this.handleClick.bind(this);
this.performGistAction = this.performGistAction.bind(this);
this.setPrivate = this.setPrivate.bind(this);
this.setPublic = this.setPublic.bind(this);
this.state = {
isUpdating: false,
isDeleting: false,
actionType: GistActionType.publish,
};
}
private toaster: Toaster;
private refHandlers = {
toaster: (ref: Toaster) => (this.toaster = ref),
};
public componentDidMount() {
ipcRendererManager.on(IpcEvents.FS_SAVE_FIDDLE_GIST, this.handleClick);
}
public componentWillUnmount() {
ipcRendererManager.off(IpcEvents.FS_SAVE_FIDDLE_GIST, this.handleClick);
}
/**
* When the user clicks the publish button, we either show the
* authentication dialog or publish right away.
*
* If we're showing the authentication dialog, we wait for it
* to be closed again (or a GitHub token to show up) before
* we publish
*
* @returns {Promise<void>}
* @memberof GistActionButton
*/
public async handleClick(): Promise<void> {
const { appState } = this.props;
if (!appState.gitHubToken) {
appState.toggleAuthDialog();
}
// Wait for the dialog to be closed again
await when(() => !!appState.gitHubToken || !appState.isTokenDialogShowing);
if (appState.gitHubToken) {
return this.performGistAction();
}
}
public async getFiddleDescriptionFromUser(): Promise<string> {
const { appState } = this.props;
// Reset potentially non-null last description.
appState.genericDialogLastInput = null;
appState.setGenericDialogOptions({
type: GenericDialogType.confirm,
label: 'Please provide a brief description for your Fiddle Gist',
wantsInput: true,
ok: 'Publish',
cancel: undefined,
placeholder: 'Electron Fiddle Gist',
});
appState.isGenericDialogShowing = true;
await when(() => !appState.isGenericDialogShowing);
return appState.genericDialogLastInput ?? 'Electron Fiddle Gist';
}
/**
* Publish a new GitHub gist.
*/
public async handlePublish() {
const { appState } = this.props;
const octo = await getOctokit(this.props.appState);
const { gitHubPublishAsPublic } = this.props.appState;
const options = { includeDependencies: true, includeElectron: true };
const values = await window.ElectronFiddle.app.getEditorValues(options);
appState.activeGistAction = GistActionState.publishing;
try {
const description = await this.getFiddleDescriptionFromUser();
const gist = await octo.gists.create({
public: !!gitHubPublishAsPublic,
description,
files: this.gistFilesList(values) as any, // Note: GitHub messed up, GistsCreateParamsFiles is an incorrect interface
});
appState.gistId = gist.data.id;
appState.localPath = undefined;
console.log(`Publish Button: Publishing complete`, { gist });
this.renderToast({ message: 'Publishing completed successfully!' });
// Only set action type to update if publish completed successfully.
this.setActionType(GistActionType.update);
} catch (error) {
console.warn(`Could not publish gist`, { error });
const messageBoxOptions: Electron.MessageBoxOptions = {
message:
'Publishing Fiddle to GitHub failed. Are you connected to the Internet?',
detail: `GitHub encountered the following error: ${error.message}`,
};
ipcRendererManager.send(IpcEvents.SHOW_WARNING_DIALOG, messageBoxOptions);
}
// Ensure any previous input is reset.
appState.genericDialogLastInput = null;
appState.activeGistAction = GistActionState.none;
}
/**
* Update an existing GitHub gist.
*/
public async handleUpdate() {
const { appState } = this.props;
const octo = await getOctokit(this.props.appState);
const options = { includeDependencies: true, includeElectron: true };
const values = await window.ElectronFiddle.app.getEditorValues(options);
appState.activeGistAction = GistActionState.updating;
try {
const gist = await octo.gists.update({
gist_id: appState.gistId!,
files: this.gistFilesList(values) as any,
});
console.log('Updating: Updating done', { gist });
this.renderToast({ message: 'Successfully updated gist!' });
} catch (error) {
console.warn(`Could not update gist`, { error });
const messageBoxOptions: Electron.MessageBoxOptions = {
message:
'Updating Fiddle Gist failed. Are you connected to the Internet and is this your Gist?',
detail: `GitHub encountered the following error: ${error.message}`,
};
ipcRendererManager.send(IpcEvents.SHOW_WARNING_DIALOG, messageBoxOptions);
}
appState.activeGistAction = GistActionState.none;
this.setActionType(GistActionType.update);
}
/**
* Delete an existing GitHub gist.
*/
public async handleDelete() {
const { appState } = this.props;
const octo = await getOctokit(this.props.appState);
appState.activeGistAction = GistActionState.deleting;
try {
const gist = await octo.gists.delete({
gist_id: appState.gistId!,
});
console.log('Deleting: Deleting done', { gist });
this.renderToast({ message: 'Successfully deleted gist!' });
} catch (error) {
console.warn(`Could not delete gist`, { error });
const messageBoxOptions: Electron.MessageBoxOptions = {
message:
'Deleting Fiddle Gist failed. Are you connected to the Internet, is this your Gist, and have you loaded it?',
detail: `GitHub encountered the following error: ${error.message}`,
};
ipcRendererManager.send(IpcEvents.SHOW_WARNING_DIALOG, messageBoxOptions);
}
appState.gistId = undefined;
appState.activeGistAction = GistActionState.none;
this.setActionType(GistActionType.publish);
}
/**
* Connect with GitHub, perform a publish/update/delete action,
* and update all related properties in the app state.
*/
public async performGistAction(): Promise<void> {
const { gistId } = this.props.appState;
const { actionType } = this.state;
if (gistId) {
switch (actionType) {
case GistActionType.publish:
await this.handlePublish();
break;
case GistActionType.update:
await this.handleUpdate();
break;
case GistActionType.delete:
await this.handleDelete();
break;
}
} else {
await this.handlePublish();
}
}
/**
* Publish fiddles as private.
*
* @memberof GistActionButton
*/
public setPrivate() {
this.setPrivacy(false);
}
/**
* Publish fiddles as public.
*
* @memberof GistActionButton
*/
public setPublic() {
this.setPrivacy(true);
}
public render() {
const { gistId, activeGistAction } = this.props.appState;
const { actionType } = this.state;
const getTextForButton = () => {
let text;
if (gistId) {
text = actionType;
} else if (activeGistAction === GistActionState.updating) {
text = 'Updating...';
} else if (activeGistAction === GistActionState.publishing) {
text = 'Publishing...';
} else if (activeGistAction === GistActionState.deleting) {
text = 'Deleting...';
} else {
text = 'Publish';
}
return text;
};
const getActionIcon = () => {
switch (actionType) {
case GistActionType.publish:
return 'upload';
case GistActionType.update:
return 'refresh';
case GistActionType.delete:
return 'delete';
}
};
const isPerformingAction = activeGistAction !== GistActionState.none;
return (
<>
<fieldset disabled={isPerformingAction}>
<ButtonGroup className="button-gist-action">
{this.renderPrivacyMenu()}
<Button
onClick={this.handleClick}
loading={isPerformingAction}
icon={getActionIcon()}
text={getTextForButton()}
/>
{this.renderGistActionMenu()}
</ButtonGroup>
</fieldset>
<Toaster
position={Position.BOTTOM_RIGHT}
ref={this.refHandlers.toaster}
/>
</>
);
}
private renderGistActionMenu = () => {
const { gistId } = this.props.appState;
const { actionType } = this.state;
if (!gistId) {
return null;
}
const menu = (
<Menu>
<MenuItem
text="Publish"
active={actionType === GistActionType.publish}
onClick={() => this.setActionType(GistActionType.publish)}
/>
<MenuItem
text="Update"
active={actionType === GistActionType.update}
onClick={() => this.setActionType(GistActionType.update)}
/>
<MenuItem
text="Delete"
active={actionType === GistActionType.delete}
onClick={() => this.setActionType(GistActionType.delete)}
/>
</Menu>
);
return (
<Popover content={menu} position={Position.BOTTOM}>
<Button icon="wrench" />
</Popover>
);
};
private renderPrivacyMenu = () => {
const { gitHubPublishAsPublic, gistId } = this.props.appState;
if (gistId) {
return null;
}
const privacyIcon = gitHubPublishAsPublic ? 'unlock' : 'lock';
const privacyMenu = (
<Menu>
<MenuItem
text="Private"
icon="lock"
active={!gitHubPublishAsPublic}
onClick={this.setPrivate}
/>
<MenuItem
text="Public"
icon="unlock"
active={gitHubPublishAsPublic}
onClick={this.setPublic}
/>
</Menu>
);
return (
<Popover content={privacyMenu} position={Position.BOTTOM}>
<Button icon={privacyIcon} />
</Popover>
);
};
private setActionType = (actionType: GistActionType) => {
this.setState({ actionType });
};
private setPrivacy(publishAsPublic: boolean) {
this.props.appState.gitHubPublishAsPublic = publishAsPublic;
}
private renderToast = (toast: IToastProps) => {
this.toaster.show(toast);
};
private gistFilesList = (values: EditorValues) => {
return {
[INDEX_HTML_NAME]: {
content: values.html || EMPTY_EDITOR_CONTENT.html,
},
[MAIN_JS_NAME]: {
content: values.main || EMPTY_EDITOR_CONTENT.js,
},
[RENDERER_JS_NAME]: {
content: values.renderer || EMPTY_EDITOR_CONTENT.js,
},
[PRELOAD_JS_NAME]: {
content: values.preload || EMPTY_EDITOR_CONTENT.js,
},
[STYLES_CSS_NAME]: {
content: values.css || EMPTY_EDITOR_CONTENT.css,
},
};
};
}
@@ -0,0 +1,147 @@
import { Button, InputGroup, Intent } from '@blueprintjs/core';
import classnames from 'classnames';
import { reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { IpcEvents } from '../../ipc-events';
import { GistActionState } from '../../interfaces';
import { idFromUrl, urlFromId } from '../../utils/gist';
import { ipcRendererManager } from '../ipc';
import { AppState } from '../state';
export interface AddressBarProps {
appState: AppState;
}
export interface AddressBarState {
value: string;
loaders: {
gist: any;
example: any;
};
}
@observer
export class AddressBar extends React.Component<
AddressBarProps,
AddressBarState
> {
constructor(props: AddressBarProps) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
this.submit = this.submit.bind(this);
const { gistId } = this.props.appState;
const value = urlFromId(gistId);
const { remoteLoader } = window.ElectronFiddle.app;
this.state = {
value,
loaders: {
gist: remoteLoader.loadFiddleFromGist.bind(remoteLoader),
example: remoteLoader.loadFiddleFromElectronExample.bind(remoteLoader),
},
};
}
/**
* Handle the form's submit event, trying to load whatever
* URL was entered.
*
* @param {React.SyntheticEvent<HTMLFormElement>} event
*/
public handleSubmit(event: React.SyntheticEvent<HTMLFormElement>) {
event.preventDefault();
this.submit();
}
/**
* Commit the address bar's value to app state and load the fiddle.
*
* @memberof AddressBar
*/
public submit() {
const { remoteLoader } = window.ElectronFiddle.app;
if (this.state.value) {
remoteLoader.fetchGistAndLoad(
idFromUrl(this.state.value) || this.state.value,
);
}
}
/**
* Once the component mounts, we'll subscribe to gistId changes
*/
public componentDidMount() {
const { appState } = this.props;
const { loaders } = this.state;
reaction(
() => appState.gistId,
(gistId: string) => this.setState({ value: urlFromId(gistId) }),
);
ipcRendererManager.on(IpcEvents.LOAD_GIST_REQUEST, loaders.gist);
ipcRendererManager.on(
IpcEvents.LOAD_ELECTRON_EXAMPLE_REQUEST,
loaders.example,
);
}
public componentWillUnmount() {
const { loaders } = this.state;
ipcRendererManager.removeListener(
IpcEvents.LOAD_GIST_REQUEST,
loaders.gist,
);
ipcRendererManager.removeListener(
IpcEvents.LOAD_ELECTRON_EXAMPLE_REQUEST,
loaders.example,
);
}
/**
* Handle the change event, which usually just updates the address bar's value
*
* @param {React.ChangeEvent<HTMLInputElement>} event
*/
public handleChange(event: React.ChangeEvent<HTMLInputElement>) {
this.setState({ value: event.target.value });
}
public renderLoadButton(isValueCorrect: boolean): JSX.Element {
return (
<Button
disabled={!isValueCorrect}
icon="cloud-download"
text="Load Fiddle"
onClick={this.submit}
/>
);
}
public render() {
const { isUnsaved, activeGistAction } = this.props.appState;
const { value } = this.state;
const isCorrect = /https:\/\/gist\.github\.com\/(.+)$/.test(value);
const className = classnames('address-bar', isUnsaved, { empty: !value });
const isPerformingAction = activeGistAction !== GistActionState.none;
return (
<form className={className} onSubmit={this.handleSubmit}>
<fieldset disabled={isPerformingAction}>
<InputGroup
key="addressbar"
leftIcon="geosearch"
intent={isCorrect || !value ? undefined : Intent.DANGER}
onChange={this.handleChange}
placeholder="https://gist.github.com/..."
value={value}
rightElement={this.renderLoadButton(isCorrect)}
/>
</fieldset>
</form>
);
}
}
@@ -0,0 +1,95 @@
import { Button } from '@blueprintjs/core';
import { observer } from 'mobx-react';
import * as React from 'react';
import { GenericDialogType, VersionState } from '../../../src/interfaces';
import { AppState } from '../state';
interface BisectHandlerProps {
appState: AppState;
}
@observer
export class BisectHandler extends React.Component<BisectHandlerProps> {
constructor(props: BisectHandlerProps) {
super(props);
this.continueBisect = this.continueBisect.bind(this);
this.terminateBisect = this.terminateBisect.bind(this);
}
public continueBisect(isGood: boolean) {
window.ElectronFiddle.app.runner.stop();
const { appState } = this.props;
const response = appState.Bisector!.continue(isGood);
if (Array.isArray(response)) {
this.terminateBisect();
const [minRev, maxRev] = response;
const [minVer, maxVer] = [minRev.version, maxRev.version];
const label = (
<>
Bisect complete. Check the range{' '}
<a
target="_blank"
rel="noreferrer"
href={`https://github.com/electron/electron/compare/v${minVer}...v${maxVer}`}
>
{minVer}...{maxVer}
</a>
.
</>
);
appState.pushOutput(`[BISECT] Complete: ${minVer}...${maxVer}`);
appState.setGenericDialogOptions({
type: GenericDialogType.success,
label,
cancel: undefined,
});
appState.isGenericDialogShowing = true;
} else {
appState.setVersion(response.version);
}
}
public terminateBisect() {
const { appState } = this.props;
appState.Bisector = undefined;
}
public render() {
const { appState } = this.props;
if (!!appState.Bisector) {
const isDownloading =
appState.currentElectronVersion.state === VersionState.downloading;
return (
<>
<Button
icon={'thumbs-up'}
onClick={() => this.continueBisect(true)}
disabled={isDownloading}
/>
<Button
icon={'thumbs-down'}
onClick={() => this.continueBisect(false)}
disabled={isDownloading}
/>
<Button icon={'cross'} onClick={this.terminateBisect}>
Cancel Bisect
</Button>
</>
);
} else {
return (
<Button
icon="git-branch"
text="Bisect"
onClick={appState.toggleBisectDialog}
/>
);
}
}
}
@@ -0,0 +1,119 @@
import {
Button,
Menu,
MenuDivider,
MenuItem,
Popover,
Position,
} from '@blueprintjs/core';
import { observer } from 'mobx-react';
import * as React from 'react';
import { ALL_EDITORS, MosaicId, PanelId } from '../../interfaces';
import { getVisibleMosaics } from '../../utils/editors-mosaic-arrangement';
import { AppState } from '../state';
import { TITLE_MAP } from './editors';
export interface EditorDropdownState {
value: string;
}
export interface EditorDropdownProps {
appState: AppState;
}
/**
* A dropdown allowing users to toggle the various editors
*
* @class EditorDropdown
* @extends {React.Component<EditorDropdownProps, EditorDropdownState>}
*/
@observer
export class EditorDropdown extends React.Component<
EditorDropdownProps,
EditorDropdownState
> {
constructor(props: EditorDropdownProps) {
super(props);
this.onItemClick = this.onItemClick.bind(this);
}
public render() {
return (
<>
<Popover content={this.renderMenu()} position={Position.BOTTOM}>
<Button icon="applications" text="Editors" />
</Popover>
{this.renderDocsDemos()}
</>
);
}
public renderDocsDemos() {
if (!process.env.FIDDLE_DOCS_DEMOS) {
return null;
}
return (
<Button
icon="help"
text="Docs & Demos"
id={PanelId.docsDemo}
onClick={this.onItemClick}
active={!this.props.appState.closedPanels.docsDemo}
/>
);
}
public renderMenu() {
return <Menu>{...this.renderMenuItems()}</Menu>;
}
public renderMenuItems() {
const { appState } = this.props;
const result: Array<JSX.Element> = [];
const visibleMosaics = getVisibleMosaics(appState.mosaicArrangement);
for (const id of ALL_EDITORS) {
result.push(
<MenuItem
icon={visibleMosaics.includes(id) ? 'eye-open' : 'eye-off'}
key={id}
text={TITLE_MAP[id]}
id={id}
onClick={this.onItemClick}
disabled={appState.mosaicArrangement === id} // can't hide last editor panel
/>,
);
}
result.push(
<React.Fragment key={'fragment-reset-layout'}>
<MenuDivider />
<MenuItem
icon="grid-view"
key="reset-layout"
text="Reset Layout"
onClick={appState.resetEditorLayout}
/>
</React.Fragment>,
);
return result;
}
public onItemClick(event: React.MouseEvent) {
const { id } = event.currentTarget;
const { appState } = this.props;
const visibleMosaics = getVisibleMosaics(appState.mosaicArrangement);
if (visibleMosaics.includes(id as MosaicId)) {
console.log(`EditorDropdown: Closing ${id}`);
appState.hideAndBackupMosaic(id as MosaicId);
} else {
console.log(`EditorDropdown: Opening ${id}`);
appState.showMosaic(id as MosaicId);
}
}
}
@@ -0,0 +1,55 @@
import { Button, IButtonProps, Spinner } from '@blueprintjs/core';
import { observer } from 'mobx-react';
import * as React from 'react';
import { VersionState } from '../../interfaces';
import { AppState } from '../state';
export interface RunnerProps {
appState: AppState;
}
/**
* The runner component is responsible for actually launching the fiddle
* with Electron. It also renders the button that does so.
*
* @class Runner
* @extends {React.Component<RunnerProps>}
*/
@observer
export class Runner extends React.Component<RunnerProps> {
public render() {
const { isRunning, currentElectronVersion } = this.props.appState;
const state = currentElectronVersion && currentElectronVersion.state;
const props: IButtonProps = { className: 'button-run', disabled: true };
if (state === VersionState.downloading) {
props.text = 'Downloading';
props.icon = (
<Spinner size={16} value={currentElectronVersion?.downloadProgress} />
);
} else if (state === VersionState.unzipping) {
props.text = 'Unzipping';
props.icon = <Spinner size={16} />;
} else if (state === VersionState.ready) {
props.disabled = false;
if (isRunning) {
props.active = true;
props.text = 'Stop';
props.onClick = window.ElectronFiddle.app.runner.stop;
props.icon = 'stop';
} else {
props.text = 'Run';
props.onClick = window.ElectronFiddle.app.runner.run;
props.icon = 'play';
}
} else {
props.text = 'Checking status';
props.icon = <Spinner size={16} />;
}
return <Button {...props} type={undefined} />;
}
}
@@ -0,0 +1,29 @@
import { ButtonGroup } from '@blueprintjs/core';
import { observer } from 'mobx-react';
import * as React from 'react';
import { AppState } from '../state';
import { VersionSelect } from './version-select';
export interface VersionChooserProps {
appState: AppState;
}
/**
* A dropdown allowing the selection of Electron versions. The actual
* download is managed in the state.
*/
export const VersionChooser = observer((props: VersionChooserProps) => {
const { currentElectronVersion, Bisector, setVersion } = props.appState;
return (
<ButtonGroup>
<VersionSelect
appState={props.appState}
onVersionSelect={({ version }) => setVersion(version)}
currentVersion={currentElectronVersion}
disabled={!!Bisector}
/>
</ButtonGroup>
);
});
+41 -19
View File
@@ -1,39 +1,61 @@
import * as React from 'react';
import { Button, ControlGroup } from '@blueprintjs/core';
import { observer } from 'mobx-react';
import * as Icon from '@fortawesome/react-fontawesome';
import { faTerminal } from '@fortawesome/fontawesome-free-solid';
import * as React from 'react';
import { Runner } from './runner';
import { VersionChooser } from './version-chooser';
import { AppState } from '../app';
import { AppState } from '../state';
import { AddressBar } from './commands-address-bar';
import { BisectHandler } from './commands-bisect';
import { EditorDropdown } from './commands-editors';
import { GistActionButton } from './commands-action-button';
import { Runner } from './commands-runner';
import { VersionChooser } from './commands-version-chooser';
export interface CommandsProps {
appState: AppState;
}
/**
* The command bar, containing all the buttons doing
* all the things
*
* @class Commands
* @extends {React.Component<CommandsProps>}
*/
@observer
export class Commands extends React.Component<CommandsProps, {}> {
export class Commands extends React.Component<CommandsProps> {
constructor(props: CommandsProps) {
super(props);
this.toggleConsole = this.toggleConsole.bind(this);
}
public toggleConsole() {
this.props.appState.isConsoleShowing = !this.props.appState.isConsoleShowing;
}
public render() {
const { appState } = this.props;
const { isBisectCommandShowing: isBisectCommandShowing } = appState;
return (
<div className='commands'>
<div className="commands">
<div>
<Runner appState={this.props.appState} />
<VersionChooser appState={this.props.appState} />
<ControlGroup fill={true} vertical={false}>
<VersionChooser appState={appState} />
<Runner appState={appState} />
</ControlGroup>
{isBisectCommandShowing && (
<ControlGroup fill={true} vertical={false}>
<BisectHandler appState={appState} />
</ControlGroup>
)}
<ControlGroup fill={true} vertical={false}>
<Button
active={appState.isConsoleShowing}
icon="console"
text="Console"
onClick={appState.toggleConsole}
/>
<EditorDropdown appState={appState} />
</ControlGroup>
</div>
<div>
<button className='button' onClick={this.toggleConsole}>
<Icon icon={faTerminal} />
</button>
<AddressBar appState={appState} />
<GistActionButton appState={appState} />
</div>
</div>
);
@@ -0,0 +1,168 @@
import { Button, Dialog, FileInput } from '@blueprintjs/core';
import { shell } from 'electron';
import * as fsType from 'fs-extra';
import { observer } from 'mobx-react';
import * as MonacoType from 'monaco-editor';
import * as path from 'path';
import * as React from 'react';
import { getTheme, THEMES_PATH } from '../themes';
import { GenericDialogType } from '../../../src/interfaces';
import { AppState } from '../state';
import { defaultDark, LoadedFiddleTheme } from '../themes-defaults';
export interface AddThemeDialogProps {
appState: AppState;
}
export interface AddThemeDialogState {
file?: File;
}
/**
* The "add monaco theme" dialog allows users to add custom editor themes.
*
* @class AddThemeDialog
* @extends {React.Component<AddThemeDialogProps, AddThemeDialogState>}
*/
@observer
export class AddThemeDialog extends React.Component<
AddThemeDialogProps,
AddThemeDialogState
> {
public resetState = { file: undefined };
constructor(props: AddThemeDialogProps) {
super(props);
this.state = this.resetState;
this.onSubmit = this.onSubmit.bind(this);
this.onClose = this.onClose.bind(this);
this.onChangeFile = this.onChangeFile.bind(this);
this.reset = this.reset.bind(this);
}
/**
* Handles a change of the file input
*
* @param {React.ChangeEvent<HTMLInputElement>} event
*/
public async onChangeFile(event: React.FormEvent<HTMLInputElement>) {
const { files } = event.target as any;
const file = files && files[0] ? files[0] : undefined;
this.setState({ file });
}
/**
* Handles the submission of the dialog
*
* @returns {Promise<void>}
*/
public async onSubmit(): Promise<void> {
const { file } = this.state;
const defaultTheme = !!this.props.appState.theme
? await getTheme(this.props.appState.theme)
: defaultDark;
if (!file) return;
try {
const editor = fsType.readJSONSync(file.path);
if (!editor.base && !editor.rules)
throw Error('File does not match specifications'); // has to have these attributes
defaultTheme.editor = editor as Partial<
MonacoType.editor.IStandaloneThemeData
>;
const newTheme = defaultTheme;
const name = editor.name ? editor.name : file.name;
await this.createNewThemeFromMonaco(name, newTheme);
} catch (error) {
this.props.appState.setGenericDialogOptions({
type: GenericDialogType.warning,
label: `Error: ${error}, please pick a different file.`,
});
this.props.appState.isGenericDialogShowing = true;
return;
}
this.onClose();
return;
}
public async createNewThemeFromMonaco(
name: string,
newTheme: LoadedFiddleTheme,
): Promise<boolean> {
if (!name) return false;
const themePath = path.join(THEMES_PATH, `${name}`);
await fsType.outputJSON(
themePath,
{
...newTheme,
name,
},
{ spaces: 2 },
);
this.props.appState.setTheme(themePath);
shell.showItemInFolder(themePath);
return true;
}
get buttons() {
const canSubmit = !!this.state.file;
return [
<Button
icon="add"
key="submit"
disabled={!canSubmit}
onClick={this.onSubmit}
text="Add"
/>,
<Button icon="cross" key="cancel" onClick={this.onClose} text="Cancel" />,
];
}
public onClose() {
this.props.appState.isThemeDialogShowing = false;
this.reset();
}
public render() {
const { isThemeDialogShowing } = this.props.appState;
const inputProps = { accept: '.json' };
const { file } = this.state;
const text = file && file.path ? file.path : `Select the Monaco file...`;
return (
<Dialog
isOpen={isThemeDialogShowing}
onClose={this.onClose}
title="Add theme"
className="dialog-add-version"
>
<div className="bp3-dialog-body">
<FileInput
onInputChange={this.onChangeFile}
inputProps={inputProps as any}
text={text}
/>
<br />
</div>
<div className="bp3-dialog-footer">
<div className="bp3-dialog-footer-actions">{this.buttons}</div>
</div>
</Dialog>
);
}
/**
* Reset this component's state
*/
private reset(): void {
this.setState(this.resetState);
return;
}
}
@@ -0,0 +1,220 @@
import {
Button,
Callout,
Dialog,
FileInput,
InputGroup,
Intent,
} from '@blueprintjs/core';
import { observer } from 'mobx-react';
import * as path from 'path';
import * as React from 'react';
import * as semver from 'semver';
import { Version } from '../../interfaces';
import { IpcEvents } from '../../ipc-events';
import { getElectronNameForPlatform } from '../../utils/electron-name';
import { getIsDownloaded } from '../binary';
import { ipcRendererManager } from '../ipc';
import { AppState } from '../state';
export interface AddVersionDialogProps {
appState: AppState;
}
export interface AddVersionDialogState {
isValidElectron: boolean;
isValidVersion: boolean;
folderPath?: string;
version: string;
}
/**
* The "add version" dialog allows users to add custom builds of Electron.
*
* @class AddVersionDialog
* @extends {React.Component<AddVersionDialogProps, AddVersionDialogState>}
*/
@observer
export class AddVersionDialog extends React.Component<
AddVersionDialogProps,
AddVersionDialogState
> {
constructor(props: AddVersionDialogProps) {
super(props);
this.state = {
isValidVersion: false,
isValidElectron: false,
version: '',
};
this.onSubmit = this.onSubmit.bind(this);
this.onClose = this.onClose.bind(this);
this.onChangeVersion = this.onChangeVersion.bind(this);
ipcRendererManager.on(
IpcEvents.LOAD_LOCAL_VERSION_FOLDER,
(_event, [file]) => {
this.setFolderPath(file);
},
);
}
public componentWillUnmount() {
ipcRendererManager.removeAllListeners(IpcEvents.LOAD_LOCAL_VERSION_FOLDER);
}
/**
* Handles a change of the file input
*
* @param {React.ChangeEvent<HTMLInputElement>} event
*/
public async setFolderPath(folderPath: string) {
const isValidElectron = !!(await getIsDownloaded('custom', folderPath));
this.setState({ folderPath, isValidElectron });
}
public onChangeVersion(event: React.ChangeEvent<HTMLInputElement>) {
const version = event.target.value || '';
const isValidVersion = !!semver.valid(version);
this.setState({
version,
isValidVersion,
});
}
/**
* Handles the submission of the dialog
*
* @returns {Promise<void>}
*/
public async onSubmit(): Promise<void> {
const { folderPath, version } = this.state;
if (!folderPath) return;
const name = folderPath.slice(-20).split(path.sep).slice(1).join(path.sep);
const toAdd: Version = {
localPath: folderPath,
version,
name,
};
this.props.appState.addLocalVersion(toAdd);
this.onClose();
}
/**
* Closes the dialog
*/
public onClose() {
this.props.appState.isAddVersionDialogShowing = false;
this.reset();
}
get buttons() {
const canSubmit = this.state.isValidElectron && this.state.isValidVersion;
return [
<Button
icon="add"
key="submit"
disabled={!canSubmit}
onClick={this.onSubmit}
text="Add"
/>,
<Button icon="cross" key="cancel" onClick={this.onClose} text="Cancel" />,
];
}
public render() {
const { isAddVersionDialogShowing } = this.props.appState;
const inputProps = {
onClick: (e: React.MouseEvent<HTMLInputElement, MouseEvent>) => {
e.preventDefault();
ipcRendererManager.send(IpcEvents.SHOW_LOCAL_VERSION_FOLDER_DIALOG);
},
};
const { folderPath } = this.state;
const text =
folderPath ||
`Select the folder containing ${getElectronNameForPlatform()}...`;
return (
<Dialog
isOpen={isAddVersionDialogShowing}
onClose={this.onClose}
title="Add local Electron build"
className="dialog-add-version"
>
<div className="bp3-dialog-body">
<FileInput
id="custom-electron-version"
inputProps={inputProps as any}
text={text}
/>
<br />
{this.renderPath()}
</div>
<div className="bp3-dialog-footer">
<div className="bp3-dialog-footer-actions">{this.buttons}</div>
</div>
</Dialog>
);
}
private renderPath(): JSX.Element | null {
const { folderPath, isValidElectron } = this.state;
if (!folderPath) return null;
const info = isValidElectron
? `We found an ${getElectronNameForPlatform()} in this folder.`
: `We did not find a ${getElectronNameForPlatform()} in this folder...`;
return (
<Callout>
{info}
{this.renderVersionInput()}
</Callout>
);
}
private renderVersionInput(): JSX.Element | null {
const { isValidElectron, isValidVersion, version } = this.state;
if (!isValidElectron) return null;
return (
<>
<p>
Please specify a version, used for typings and the name. Must be{' '}
<code>semver</code> compliant.
</p>
<InputGroup
intent={isValidVersion ? undefined : Intent.DANGER}
value={version}
onChange={this.onChangeVersion}
placeholder="4.0.0"
/>
</>
);
}
/**
* Reset this component's state
*/
private reset(): void {
this.setState({
isValidElectron: false,
isValidVersion: false,
version: '',
folderPath: undefined,
});
}
}
+234
View File
@@ -0,0 +1,234 @@
import { Button, ButtonGroup, Callout, Dialog, Label } from '@blueprintjs/core';
import { observer } from 'mobx-react';
import * as React from 'react';
import { RunnableVersion } from '../../interfaces';
import { Bisector } from '../bisect';
import { AppState } from '../state';
import { VersionSelect } from './version-select';
export interface BisectDialogProps {
appState: AppState;
}
export interface BisectDialogState {
startIndex: number;
endIndex: number;
allVersions: Array<RunnableVersion>;
showHelp?: boolean;
}
/**
* The "add version" dialog allows users to add custom builds of Electron.
*
* @class BisectDialog
* @extends {React.Component<BisectDialogProps, BisectDialogState>}
*/
@observer
export class BisectDialog extends React.Component<
BisectDialogProps,
BisectDialogState
> {
constructor(props: BisectDialogProps) {
super(props);
this.onSubmit = this.onSubmit.bind(this);
this.onClose = this.onClose.bind(this);
this.onBeginSelect = this.onBeginSelect.bind(this);
this.onEndSelect = this.onEndSelect.bind(this);
this.showHelp = this.showHelp.bind(this);
this.isEarliestItemDisabled = this.isEarliestItemDisabled.bind(this);
this.isLatestItemDisabled = this.isLatestItemDisabled.bind(this);
this.state = {
allVersions: this.props.appState.versionsToShow,
startIndex: 10,
endIndex: 0,
};
}
public onBeginSelect(version: RunnableVersion) {
this.setState({ startIndex: this.state.allVersions.indexOf(version) });
}
public onEndSelect(version: RunnableVersion) {
this.setState({ endIndex: this.state.allVersions.indexOf(version) });
}
/**
* Handles the submission of the dialog
*
* @returns {Promise<void>}
*/
public async onSubmit(): Promise<void> {
const { endIndex, startIndex, allVersions } = this.state;
const { appState } = this.props;
if (endIndex === undefined || startIndex === undefined) {
return;
}
const bisectRange = allVersions.slice(endIndex, startIndex + 1).reverse();
appState.Bisector = new Bisector(bisectRange);
const initialBisectPivot = appState.Bisector.getCurrentVersion().version;
appState.setVersion(initialBisectPivot);
this.onClose();
}
/**
* Closes the dialog
*/
public onClose() {
this.props.appState.isBisectDialogShowing = false;
}
/**
* Shows the additional help
*/
public showHelp() {
this.setState({ showHelp: true });
}
/**
* Can we get this show on the road?
*/
get canSubmit(): boolean {
return this.state.startIndex > this.state.endIndex;
}
/**
* Renders the buttons
*/
get buttons() {
return [
<Button
icon="play"
key="submit"
disabled={!this.canSubmit}
onClick={this.onSubmit}
text="Begin"
/>,
<Button icon="cross" key="cancel" onClick={this.onClose} text="Cancel" />,
];
}
/**
* Renders the help
*/
get help() {
let moreHelp = (
<Button icon="help" text="Show help" onClick={this.showHelp} />
);
if (this.state.showHelp) {
moreHelp = (
<>
<p>
First, write a fiddle that reproduces a bug or an issue. Then,
select the earliest version to start your search with. Typically,
that&apos;s the &quot;last known good&quot; version that did not
have the bug. Then, select that latest version to end the search
with, usually the &quot;first known bad&quot; version.
</p>
<p>
Once you begin your bisect, Fiddle will run your fiddle with a
number of Electron versions, closing in on the version that
introduced the bug. Once completed, you will know which Electron
version introduced your issue.
</p>
</>
);
}
return (
<Callout style={{ marginTop: 0, marginBottom: '1rem' }}>
<p>
A &quot;bisect&quot; is a popular method{' '}
<a
href="https://git-scm.com/docs/git-bisect"
target="_blank"
rel="noreferrer"
>
borrowed from <code>git</code>
</a>{' '}
for learning which version of Electron introduced a bug. This tool
helps you perform a bisect.
</p>
{moreHelp}
</Callout>
);
}
public render() {
const { isBisectDialogShowing } = this.props.appState;
const { startIndex, endIndex, allVersions } = this.state;
return (
<Dialog
isOpen={isBisectDialogShowing}
onClose={this.onClose}
title="Start a bisect session"
className="dialog-add-version"
>
<div className="bp3-dialog-body">
{this.help}
<Label>
Earliest Version (Last &quot;known good&quot; version)
<ButtonGroup fill={true}>
<VersionSelect
currentVersion={allVersions[startIndex]}
appState={this.props.appState}
onVersionSelect={this.onBeginSelect}
itemDisabled={this.isEarliestItemDisabled}
/>
</ButtonGroup>
</Label>
<Label>
Latest Version (First &quot;known bad&quot; version)
<ButtonGroup fill={true}>
<VersionSelect
currentVersion={allVersions[endIndex]}
appState={this.props.appState}
onVersionSelect={this.onEndSelect}
itemDisabled={this.isLatestItemDisabled}
/>
</ButtonGroup>
</Label>
</div>
<div className="bp3-dialog-footer">
<div className="bp3-dialog-footer-actions">{this.buttons}</div>
</div>
</Dialog>
);
}
/**
* Should an item in the "earliest version" dropdown be disabled?
*
* @param {RunnableVersion} version
* @returns {boolean}
*/
public isEarliestItemDisabled(version: RunnableVersion): boolean {
const { allVersions, endIndex } = this.state;
// In the array, "newer" versions will have a lower index.
// 0: 5.0.0
// 1: 4.0.0
// 2: 3.0.0
// ...
return allVersions.indexOf(version) < endIndex + 1;
}
/**
* Should an item in the "latest version" dropdown be disabled?
*
* @param {RunnableVersion} version
* @returns {boolean}
*/
public isLatestItemDisabled(version: RunnableVersion): boolean {
const { allVersions, startIndex } = this.state;
return allVersions.indexOf(version) > startIndex - 1;
}
}
@@ -0,0 +1,94 @@
import { Alert, IconName, InputGroup, Intent } from '@blueprintjs/core';
import { observer } from 'mobx-react';
import * as React from 'react';
import { GenericDialogType } from '../../../src/interfaces';
import { AppState } from '../state';
export interface GenericDialogProps {
appState: AppState;
}
/**
* The token dialog prompts the user to either continue or cancel the operation.
*
* @export
* @class GenericDialog
* @extends {React.Component<GenericDialogProps, GenericDialogState>}
*/
@observer
export class GenericDialog extends React.Component<GenericDialogProps> {
constructor(props: GenericDialogProps) {
super(props);
this.onClose = this.onClose.bind(this);
}
public onClose(result: boolean) {
const input = document.getElementById('input') as HTMLInputElement;
this.props.appState.genericDialogLastInput =
input && input.value !== '' ? input.value : null;
this.props.appState.genericDialogLastResult = result;
this.props.appState.toggleGenericDialog();
}
public render() {
const {
isGenericDialogShowing,
genericDialogOptions,
} = this.props.appState;
const {
type,
ok,
cancel,
label,
wantsInput,
placeholder,
} = genericDialogOptions;
let intent: Intent;
let icon: IconName;
switch (type) {
case GenericDialogType.warning:
intent = Intent.DANGER;
icon = 'warning-sign';
break;
case GenericDialogType.confirm:
intent = Intent.PRIMARY;
icon = 'help';
break;
case GenericDialogType.success:
intent = Intent.SUCCESS;
icon = 'info-sign';
break;
default:
intent = Intent.NONE;
icon = 'help';
break;
}
let dialogInput;
if (wantsInput) {
dialogInput = placeholder ? (
<InputGroup id="input" placeholder={placeholder} />
) : (
<InputGroup id="input" />
);
}
return (
<Alert
isOpen={isGenericDialogShowing}
onClose={this.onClose}
icon={icon}
confirmButtonText={ok}
cancelButtonText={cancel}
intent={intent}
>
<p>{label}</p>
{wantsInput && dialogInput}
</Alert>
);
}
}
+199
View File
@@ -0,0 +1,199 @@
import { Button, Callout, Dialog, InputGroup, Intent } from '@blueprintjs/core';
import { clipboard, shell } from 'electron';
import { observer } from 'mobx-react';
import * as React from 'react';
import { getOctokit } from '../../utils/octokit';
import { AppState } from '../state';
export interface TokenDialogProps {
appState: AppState;
}
export interface TokenDialogState {
tokenInput: string;
verifying: boolean;
error: boolean;
}
const TOKEN_SCOPES = ['gist'].join();
const TOKEN_DESCRIPTION = encodeURIComponent('Fiddle Gist Token');
const GENERATE_TOKEN_URL = `https://github.com/settings/tokens/new?scopes=${TOKEN_SCOPES}&description=${TOKEN_DESCRIPTION}`;
/**
* The token dialog asks the user for a GitHub Personal Access Token.
* It's also responsible for checking if the token is correct.
*
* @export
* @class TokenDialog
* @extends {React.Component<TokenDialogProps, TokenDialogState>}
*/
@observer
export class TokenDialog extends React.Component<
TokenDialogProps,
TokenDialogState
> {
constructor(props: TokenDialogProps) {
super(props);
this.state = {
verifying: false,
error: false,
tokenInput: '',
};
this.onSubmitToken = this.onSubmitToken.bind(this);
this.openGenerateTokenExternal = this.openGenerateTokenExternal.bind(this);
this.onTokenInputFocused = this.onTokenInputFocused.bind(this);
this.handleChange = this.handleChange.bind(this);
this.onClose = this.onClose.bind(this);
}
/**
* Handles the submission of a token
*
* @returns {Promise<void>}
* @memberof TokenDialog
*/
public async onSubmitToken(): Promise<void> {
if (!this.state.tokenInput) return;
this.setState({ verifying: true });
this.props.appState.gitHubToken = this.state.tokenInput;
const octo = await getOctokit(this.props.appState);
try {
const { data } = await octo.users.getAuthenticated();
this.props.appState.gitHubAvatarUrl = data.avatar_url;
this.props.appState.gitHubLogin = data.login;
this.props.appState.gitHubName = data.name;
this.setState({ verifying: false, error: false });
} catch (error) {
console.warn(`Authenticating against GitHub failed`, error);
this.setState({ verifying: false, error: true });
this.props.appState.gitHubToken = null;
return;
}
this.props.appState.isTokenDialogShowing = false;
}
/**
* Closes the dialog
*/
public onClose() {
this.props.appState.isTokenDialogShowing = false;
this.reset();
}
/**
* Reset this component's state
*/
public reset(): void {
this.setState({
verifying: false,
error: false,
tokenInput: '',
});
}
/**
* Opens GitHub's page for token generation
*
* @memberof TokenDialog
*/
public openGenerateTokenExternal() {
shell.openExternal(GENERATE_TOKEN_URL);
}
/**
* When the input field receives focus, we check the clipboard.
* Maybe there's already something token-like there!
*
* @returns
* @memberof TokenDialog
*/
public onTokenInputFocused() {
const text = (clipboard.readText() || '').trim();
if (text.length !== 40) return;
if (!/^[a-z0-9]+$/.test(text)) return;
this.setState({ tokenInput: text });
}
/**
* Handle the change event, which usually just updates the address bar's value
*
* @param {React.ChangeEvent<HTMLInputElement>} event
* @memberof AddressBar
*/
public handleChange(event: React.ChangeEvent<HTMLInputElement>) {
this.setState({ tokenInput: event.target.value });
}
get buttons() {
const canSubmit = !!this.state.tokenInput;
return [
<Button
key="done"
disabled={!canSubmit}
onClick={this.onSubmitToken}
loading={this.state.verifying}
text="Done"
icon="log-in"
/>,
<Button
key="cancel"
text="Cancel"
icon="log-out"
onClick={this.onClose}
/>,
];
}
get invalidWarning() {
return (
<>
<Callout intent={Intent.DANGER}>
Please provide a valid GitHub Personal Access Token
</Callout>
<br />
</>
);
}
public render() {
const { isTokenDialogShowing } = this.props.appState;
return (
<Dialog
isOpen={isTokenDialogShowing}
onClose={this.onClose}
title="GitHub Token"
>
<div className="bp3-dialog-body">
<p>
Generate a{' '}
<a onClick={this.openGenerateTokenExternal}>
GitHub Personal Access Token
</a>{' '}
and paste it here:
</p>
{this.state.error ? this.invalidWarning : null}
<InputGroup
value={this.state.tokenInput || ''}
onFocus={this.onTokenInputFocused}
onChange={this.handleChange}
/>
</div>
<div className="bp3-dialog-footer">
<div className="bp3-dialog-footer-actions">{this.buttons}</div>
</div>
</Dialog>
);
}
}
+64
View File
@@ -0,0 +1,64 @@
import { observer } from 'mobx-react';
import * as React from 'react';
import { AppState } from '../state';
import { AddThemeDialog } from './dialog-add-theme';
import { AddVersionDialog } from './dialog-add-version';
import { BisectDialog } from './dialog-bisect';
import { GenericDialog } from './dialog-generic';
import { TokenDialog } from './dialog-token';
import { Settings } from './settings';
export interface DialogsProps {
appState: AppState;
}
/**
* Dialogs (like the GitHub PAT input).
*
* @class Dialogs
* @extends {React.Component<DialogsProps, {}>}
*/
@observer
export class Dialogs extends React.Component<DialogsProps> {
public render() {
const { appState } = this.props;
const {
isTokenDialogShowing,
isSettingsShowing,
isAddVersionDialogShowing,
isThemeDialogShowing,
isBisectDialogShowing,
isGenericDialogShowing,
} = appState;
const maybeToken = isTokenDialogShowing ? (
<TokenDialog key="dialogs" appState={appState} />
) : null;
const maybeSettings = isSettingsShowing ? (
<Settings key="settings" appState={appState} />
) : null;
const maybeAddLocalVersion = isAddVersionDialogShowing ? (
<AddVersionDialog key="add-version-dialog" appState={appState} />
) : null;
const maybeMonaco = isThemeDialogShowing ? (
<AddThemeDialog appState={appState} />
) : null;
const maybeBisect = isBisectDialogShowing ? (
<BisectDialog key="bisect-dialog" appState={appState} />
) : null;
const genericDialog = isGenericDialogShowing ? (
<GenericDialog appState={appState} />
) : null;
return (
<div key="dialogs" className="dialogs">
{maybeToken}
{maybeSettings}
{maybeAddLocalVersion}
{maybeMonaco}
{maybeBisect}
{genericDialog}
</div>
);
}
}
-13
View File
@@ -1,13 +0,0 @@
import * as React from 'react';
export class EditorTitle extends React.Component {
public render() {
return (
<div className='editorTitle'>
<span>Main Process</span>
<span>Renderer Process</span>
<span>HTML</span>
</div>
);
}
}
+167
View File
@@ -0,0 +1,167 @@
// Credit goes in large part to https://github.com/superRaytin/react-monaco-editor,
// this component is a changed version of it.
import * as MonacoType from 'monaco-editor';
import * as React from 'react';
import { EditorId } from '../../interfaces';
import { getContent } from '../content';
import { AppState } from '../state';
export interface EditorProps {
appState: AppState;
monaco: typeof MonacoType;
monacoOptions: MonacoType.editor.IEditorOptions;
id: EditorId;
options?: Partial<MonacoType.editor.IEditorConstructionOptions>;
editorDidMount?: (editor: MonacoType.editor.IStandaloneCodeEditor) => void;
onChange?: (
value: string,
event: MonacoType.editor.IModelContentChangedEvent,
) => void;
setFocused: (id: EditorId) => void;
}
export class Editor extends React.Component<EditorProps> {
public editor: MonacoType.editor.IStandaloneCodeEditor;
public language = 'javascript';
public value = '';
private containerRef = React.createRef<HTMLDivElement>();
constructor(props: EditorProps) {
super(props);
switch (props.id) {
case 'html':
this.language = 'html';
break;
case 'css':
this.language = 'css';
break;
default:
this.language = 'javascript';
}
}
public shouldComponentUpdate() {
return false;
}
public async componentDidMount() {
await this.initMonaco();
}
public componentWillUnmount() {
this.destroyMonaco();
}
/**
* Handle the editor having been mounted. This refers to Monaco's
* mount, not React's.
*
* @param {MonacoType.editor.IStandaloneCodeEditor} editor
*/
public async editorDidMount(editor: MonacoType.editor.IStandaloneCodeEditor) {
const { editorDidMount } = this.props;
// Set the content on the editor
await this.setContent();
// Set the editor as an available object
window.ElectronFiddle.editors[this.props.id] = editor;
// And notify others
if (editorDidMount) {
editorDidMount(editor);
}
}
/**
* Initialize Monaco.
*/
public async initMonaco() {
const { monaco, monacoOptions: monacoOptions } = this.props;
const ref = this.containerRef.current;
if (ref) {
this.editor = monaco.editor.create(ref, {
language: this.language,
theme: 'main',
contextmenu: false,
model: null,
...monacoOptions,
});
// mark this editor as focused whenever it is
this.editor.onDidFocusEditorText(() => {
const { id, setFocused } = this.props;
setFocused(id);
});
await this.editorDidMount(this.editor);
}
}
/**
* Destroy Monaco.
*/
public destroyMonaco() {
if (typeof this.editor !== 'undefined') {
console.log('Editor: Disposing');
this.editor.dispose();
}
}
public render() {
return <div className="editorContainer" ref={this.containerRef} />;
}
/**
* Create a model and attach it to the editor
*
* @private
* @param {string} value
*/
private createModel(value: string) {
const { monaco } = this.props;
const model = monaco.editor.createModel(value, this.language);
model.updateOptions({
tabSize: 2,
});
this.editor.setModel(model);
}
/**
* Sets the content on the editor, including the model and the view state.
*
* @private
* @memberof Editor
*/
private async setContent() {
const { appState, id } = this.props;
const { version } = appState;
const backup = appState.getAndRemoveEditorValueBackup(id);
if (backup) {
console.log(`Editor: Backup found, restoring state`);
if (backup.viewState) {
this.editor.restoreViewState(backup.viewState);
}
// If there's a model, use the model. No model? Use the value
if (backup.model) {
this.editor.setModel(backup.model);
} else {
this.createModel(backup.value ?? '');
}
} else {
const value = await getContent(id, version);
this.createModel(value);
}
}
}
@@ -0,0 +1,24 @@
import * as React from 'react';
import { Button, NonIdealState } from '@blueprintjs/core';
import { EditorId } from '../../interfaces';
import { AppState } from '../state';
export function renderNonIdealState(appState: AppState) {
const allEditors = [EditorId.html, EditorId.main, EditorId.renderer];
const resolveButton = (
<Button
text="Open all editors"
onClick={() => appState.setVisibleMosaics(allEditors)}
/>
);
return (
<NonIdealState
action={resolveButton}
icon="applications"
description='You have closed all editors. You can open them again with the button below or the "Editors" button above!'
/>
);
}
@@ -0,0 +1,86 @@
import * as React from 'react';
import { Button } from '@blueprintjs/core';
import {
MosaicContext,
MosaicRootActions,
MosaicWindowContext,
} from 'react-mosaic-component';
import { DocsDemoPage, MosaicId } from '../../interfaces';
import { AppState } from '../state';
export interface ToolbarButtonProps {
appState: AppState;
id: MosaicId;
}
export abstract class ToolbarButton extends React.PureComponent<
ToolbarButtonProps
> {
public static contextType = MosaicWindowContext;
public context: MosaicWindowContext;
constructor(props: ToolbarButtonProps) {
super(props);
}
public render() {
return (
<MosaicContext.Consumer>
{({ mosaicActions }) => this.createButton(mosaicActions)}
</MosaicContext.Consumer>
);
}
/**
* Create a button that performs the actual action
*/
public abstract createButton(
_mosaicActions: MosaicRootActions<any>,
): React.ReactNode;
}
export class MaximizeButton extends ToolbarButton {
/**
* Create a button that can expand this panel
*/
public createButton(mosaicActions: MosaicRootActions<any>) {
const onClick = () => {
mosaicActions.expand(this.context.mosaicWindowActions.getPath());
};
return <Button icon="maximize" className="bp3-small" onClick={onClick} />;
}
}
export class RemoveButton extends ToolbarButton {
/**
* Create a button that can remove this panel
*/
public createButton(_mosaicActions: MosaicRootActions<any>) {
const onClick = () =>
this.props.appState.hideAndBackupMosaic(this.props.id);
return <Button icon="cross" className="bp3-small" onClick={onClick} />;
}
}
export class DocsDemoGoHomeButton extends ToolbarButton {
/**
* Create a button that can remove this panel
*/
public createButton(_mosaicActions: MosaicRootActions<any>) {
const onClick = () =>
(this.props.appState.currentDocsDemoPage = DocsDemoPage.DEFAULT);
return (
<Button
icon="home"
className="bp3-small"
onClick={onClick}
text="Overview"
/>
);
}
}
+356
View File
@@ -0,0 +1,356 @@
import { reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as MonacoType from 'monaco-editor';
import * as React from 'react';
import {
Mosaic,
MosaicBranch,
MosaicNode,
MosaicWindow,
MosaicWindowProps,
} from 'react-mosaic-component';
import { EditorId, MosaicId, PanelId } from '../../interfaces';
import { IpcEvents } from '../../ipc-events';
import { updateEditorLayout } from '../../utils/editor-layout';
import { getFocusedEditor } from '../../utils/focused-editor';
import { getAtPath, setAtPath } from '../../utils/js-path';
import { toggleMonaco } from '../../utils/toggle-monaco';
import { isEditorId } from '../../utils/type-checks';
import { getContent } from '../content';
import { ipcRendererManager } from '../ipc';
import { AppState } from '../state';
import { activateTheme } from '../themes';
import { Editor } from './editor';
import { renderNonIdealState } from './editors-non-ideal-state';
import {
DocsDemoGoHomeButton,
MaximizeButton,
RemoveButton,
} from './editors-toolbar-button';
import { ShowMe } from './show-me';
const defaultMonacoOptions: MonacoType.editor.IEditorOptions = {
minimap: {
enabled: false,
},
wordWrap: 'on',
};
export const TITLE_MAP: Record<MosaicId, string> = {
main: 'Main Process (main.js)',
renderer: 'Renderer Process (renderer.js)',
preload: 'Preload (preload.js)',
html: 'HTML (index.html)',
css: 'Stylesheet (styles.css)',
docsDemo: 'Docs & Demos',
};
export interface EditorsProps {
appState: AppState;
}
export interface EditorsState {
monaco?: typeof MonacoType;
isMounted?: boolean;
monacoOptions: MonacoType.editor.IEditorOptions;
focused?: EditorId;
}
@observer
export class Editors extends React.Component<EditorsProps, EditorsState> {
// A reaction: Each time mosaicArrangement is changed, we'll update
// the editor layout. That method is itself debounced.
public disposeLayoutAutorun = reaction(
() => this.props.appState.mosaicArrangement,
() => updateEditorLayout(),
);
constructor(props: EditorsProps) {
super(props);
this.onChange = this.onChange.bind(this);
this.renderEditor = this.renderEditor.bind(this);
this.renderTile = this.renderTile.bind(this);
this.renderGenericPanel = this.renderGenericPanel.bind(this);
this.setFocused = this.setFocused.bind(this);
this.state = { monacoOptions: defaultMonacoOptions };
}
/**
* Executed right after the component mounts. We'll setup the IPC listeners here.
*
* @memberof Editors
*/
public async componentDidMount() {
ipcRendererManager.on(
IpcEvents.MONACO_EXECUTE_COMMAND,
(_event, cmd: string) => {
this.executeCommand(cmd);
},
);
ipcRendererManager.on(IpcEvents.FS_NEW_FIDDLE, async (_event) => {
const { version } = this.props.appState;
await window.ElectronFiddle.app.replaceFiddle(
{
html: await getContent(EditorId.html, version),
renderer: await getContent(EditorId.renderer, version),
main: await getContent(EditorId.main, version),
},
{},
);
});
ipcRendererManager.on(
IpcEvents.MONACO_TOGGLE_OPTION,
(_event, cmd: string) => {
this.toggleEditorOption(cmd);
},
);
ipcRendererManager.on(IpcEvents.SELECT_ALL_IN_EDITOR, (_event) => {
// programmatically fetch all editor contents and set as selection
const editor = getFocusedEditor();
const range = editor?.getModel()?.getFullModelRange();
if (!!range) {
editor?.setSelection(range);
}
});
this.setState({ isMounted: true });
await this.loadMonaco();
this.props.appState.isUnsaved = false;
}
public componentWillUnmount() {
this.disposeLayoutAutorun();
ipcRendererManager.removeAllListeners(IpcEvents.MONACO_EXECUTE_COMMAND);
ipcRendererManager.removeAllListeners(IpcEvents.FS_NEW_FIDDLE);
ipcRendererManager.removeAllListeners(IpcEvents.MONACO_TOGGLE_OPTION);
ipcRendererManager.removeAllListeners(IpcEvents.SELECT_ALL_IN_EDITOR);
}
/**
* Attempt to execute a given commandId on the currently focused editor
*
* @param {string} commandId
* @memberof Editors
*/
public executeCommand(commandId: string) {
const editor = getFocusedEditor();
if (editor) {
const command = editor.getAction(commandId);
console.log(
`Editors: Trying to run ${command.id}. Supported: ${command.isSupported}`,
);
if (command && command.isSupported()) {
command.run();
}
}
}
public toggleEditorOption(path: string): boolean {
if (!window.ElectronFiddle.editors) {
return false;
}
try {
const { monacoOptions } = this.state;
const newOptions = { ...monacoOptions };
const currentSetting = getAtPath(path, newOptions);
setAtPath(path, newOptions, toggleMonaco(currentSetting));
Object.keys(window.ElectronFiddle.editors).forEach((key) => {
const editor: MonacoType.editor.IStandaloneCodeEditor | null =
window.ElectronFiddle.editors[key];
if (editor) {
editor.updateOptions(newOptions);
}
});
this.setState({ monacoOptions: newOptions });
return true;
} catch (error) {
console.warn(`Editors: Could not toggle property ${path}`, error);
return false;
}
}
/**
* Renders the little tool bar on top of each panel
*
* @param {MosaicWindowProps<MosaicId>} { title }
* @param {MosaicId} id
* @returns {JSX.Element}
*/
public renderToolbar(
{ title }: MosaicWindowProps<MosaicId>,
id: MosaicId,
): JSX.Element {
const { appState } = this.props;
const docsDemoGoHomeMaybe =
id === PanelId.docsDemo ? (
<DocsDemoGoHomeButton id={id} appState={appState} />
) : null;
// only show toolbar controls if we have more than 1 visible editor
// Mosaic arrangement is type string if 1 editor, object otherwise
const toolbarControlsMaybe = typeof appState.mosaicArrangement !==
'string' && (
<>
<MaximizeButton id={id} appState={appState} />
<RemoveButton id={id} appState={appState} />
</>
);
return (
<div>
{/* Left */}
<div>
<h5>{title}</h5>
</div>
{/* Middle */}
<div />
{/* Right */}
<div className="mosaic-controls">
{docsDemoGoHomeMaybe}
{toolbarControlsMaybe}
</div>
</div>
);
}
/**
* Renders a Mosaic tile
*
* @param {string} id
* @param {string} path
* @returns {JSX.Element | null}
*/
public renderTile(id: MosaicId, path: Array<MosaicBranch>): JSX.Element {
const { appState } = this.props;
const content = isEditorId(id)
? this.renderEditor(id)
: this.renderGenericPanel(id, appState);
return (
<MosaicWindow<EditorId>
className={id}
path={path}
title={TITLE_MAP[id]}
renderToolbar={(props: MosaicWindowProps<MosaicId>) =>
this.renderToolbar(props, id)
}
>
{content}
</MosaicWindow>
);
}
/**
* Renders a generic panel  so not an editor, but something else
*
* @param {PanelId} _id
* @param {AppState} _appState
* @returns {JSX.Element}
*/
public renderGenericPanel(_id: PanelId, appState: AppState): JSX.Element {
return <ShowMe appState={appState} />;
}
/**
* Render an editor
*
* @param {EditorId} id
* @returns {(JSX.Element | null)}
* @memberof Editors
*/
public renderEditor(id: EditorId): JSX.Element | null {
const { appState } = this.props;
const { monaco } = this.state;
return (
<Editor
id={id}
monaco={monaco!}
appState={appState}
monacoOptions={defaultMonacoOptions}
setFocused={this.setFocused}
/>
);
}
public render() {
const { appState } = this.props;
const { monaco } = this.state;
if (!monaco) return null;
return (
<Mosaic<EditorId | PanelId>
className={`focused__${this.state.focused}`}
onChange={this.onChange}
value={appState.mosaicArrangement}
zeroStateView={renderNonIdealState(appState)}
renderTile={this.renderTile}
/>
);
}
/**
* Handles a change in the visible nodes
*
* @param {(MosaicNode<EditorId> | null)} currentNode
*/
public onChange(currentNode: MosaicNode<EditorId> | null) {
this.props.appState.mosaicArrangement = currentNode;
}
/**
* Loads monaco. If it's already loaded, it'll just set it on the current state.
* We're doing things a bit roundabout to ensure that we're not overloading the
* mobx state with a gigantic Monaco tree.
*/
public async loadMonaco() {
const { app } = window.ElectronFiddle;
const loader = require('monaco-loader');
const monaco = app.monaco || (await loader());
if (!app.monaco) {
app.monaco = monaco;
}
if (!this.state || !this.state.isMounted) {
this.setState({
monaco,
monacoOptions: defaultMonacoOptions,
});
} else {
this.setState({ monaco });
}
await activateTheme(monaco, undefined, this.props.appState.theme);
}
/**
* Sets the currently-focused editor. This will impact the editor's
* z-index, ensuring that its intellisense menus don't get clipped
* by the other editor windows.
* @param id Editor ID
*/
public setFocused(id: EditorId): void {
this.setState({ focused: id });
}
}
+20 -11
View File
@@ -1,21 +1,30 @@
import * as React from 'react';
import { observer } from 'mobx-react';
import { EditorTitle } from './editor-title';
import { AppState } from '../state';
import { ChromeMac } from './chrome-mac';
import { Commands } from './commands';
import { AppState } from '../app';
import { Output } from './output';
import { WelcomeTour } from './tour-welcome';
export interface HeaderProps {
appState: AppState;
}
@observer
export class Header extends React.Component<HeaderProps, {}> {
/**
* Everything above the editors, so buttons and the address bar.
*
* @class Header
* @extends {React.Component<HeaderProps>}
*/
export class Header extends React.Component<HeaderProps> {
public render() {
return [
<Commands key='commands' appState={this.props.appState} />,
<Output key='output' appState={this.props.appState} />,
<EditorTitle key='titles' />
];
return (
<>
<ChromeMac appState={this.props.appState} />
<header id="header">
<Commands key="commands" appState={this.props.appState} />
</header>
<WelcomeTour appState={this.props.appState} />
</>
);
}
}
@@ -0,0 +1,61 @@
import * as React from 'react';
import { Mosaic, MosaicNode } from 'react-mosaic-component';
import { AppState } from '../state';
import { Editors } from './editors';
import { Output } from './output';
export interface WrapperProps {
appState: AppState;
}
export interface WrapperState {
mosaicArrangement: MosaicNode<WrapperMosaicId>;
}
export type WrapperMosaicId = 'output' | 'editors';
export class OutputEditorsWrapper extends React.Component<
WrapperProps,
WrapperState
> {
private MOSAIC_ELEMENTS = {
output: <Output appState={this.props.appState} />,
editors: <Editors appState={this.props.appState} />,
};
constructor(props: any) {
super(props);
this.state = {
mosaicArrangement: {
direction: 'column',
first: 'output',
second: 'editors',
splitPercentage: 25,
},
};
}
public render() {
return (
<>
<Mosaic<WrapperMosaicId>
renderTile={(id: string) => this.MOSAIC_ELEMENTS[id]}
resize={{ minimumPaneSizePercentage: 0 }}
value={this.state.mosaicArrangement}
onChange={this.onChange}
/>
</>
);
}
private onChange = (currentNode: any) => {
const isConsoleShowing = currentNode.splitPercentage !== 0;
if (isConsoleShowing !== this.props.appState.isConsoleShowing) {
this.props.appState.isConsoleShowing = isConsoleShowing;
}
this.setState({ mosaicArrangement: currentNode });
};
}
+90 -14
View File
@@ -1,38 +1,114 @@
import * as React from 'react';
import { autorun } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { MosaicContext } from 'react-mosaic-component';
import { AppState } from '../app';
import { OutputEntry } from '../../interfaces';
import { AppState } from '../state';
import { WrapperMosaicId } from './output-editors-wrapper';
export interface CommandsProps {
appState: AppState;
// Used to keep testing conform
renderTimestamp?: (ts: number) => string;
}
/**
* This component represents the "console" that is shown
* whenever a Fiddle is launched in Electron.
*
* @class Output
* @extends {React.Component<CommandsProps>}
*/
@observer
export class Output extends React.Component<CommandsProps, {}> {
export class Output extends React.Component<CommandsProps> {
public static contextType = MosaicContext;
public context: MosaicContext<WrapperMosaicId>;
private outputRef = React.createRef<HTMLDivElement>();
constructor(props: CommandsProps) {
super(props);
this.renderTimestamp = this.renderTimestamp.bind(this);
this.renderEntry = this.renderEntry.bind(this);
}
public renderEntry(entry: OutputEntry) {
const ts = new Date(entry.timestamp).toLocaleTimeString();
const timestamp = <span className='timestamp'>{ts}</span>;
public componentDidMount() {
autorun(() => {
const { isConsoleShowing } = this.props.appState;
// this context should always exist, but mocking context in enzyme
// is not fully supported, so this condition makes the tests pass
if (this.context.mosaicActions && this.context.mosaicActions.expand) {
if (!isConsoleShowing) {
this.context.mosaicActions.expand(['first'], 0);
} else {
this.context.mosaicActions.expand(['first'], 25);
}
}
});
}
public componentDidUpdate() {
if (this.outputRef.current) {
this.outputRef.current.scrollTop = this.outputRef.current.scrollHeight;
}
}
/**
* Render the timestamp
*
* @param {number} ts
* @returns {string}
*/
public renderTimestamp(ts: number): string {
const { renderTimestamp } = this.props;
if (renderTimestamp) {
return renderTimestamp(ts);
} else {
return new Date(ts).toLocaleTimeString();
}
}
/**
* An individual entry might span multiple lines. To ensure that
* each line has a timestamp, this method might split up entries.
*
* @param {OutputEntry} entry
* @returns {Array<JSX.Element>}
* @memberof Output
*/
public renderEntry(entry: OutputEntry, index: number): Array<JSX.Element> {
const ts = this.renderTimestamp(entry.timestamp);
const timestamp = <span className="timestamp">{ts}</span>;
const lines = entry.text.split(/\r?\n/);
const style: React.CSSProperties = entry.isNotPre
? { whiteSpace: 'initial' }
: {};
return lines.map((text) => (
<p>{timestamp}{text}</p>
return lines.map((text, lineIndex) => (
<p style={style} key={`${entry.timestamp}--${index}--${lineIndex}`}>
{timestamp}
{text}
</p>
));
}
public render() {
const { isConsoleShowing } = this.props.appState;
const className = isConsoleShowing ? 'output showing' : 'output';
public render(): JSX.Element | null {
const { output, isConsoleShowing } = this.props.appState;
const lines = this.props.appState.output.map(this.renderEntry);
if (!isConsoleShowing) {
return null;
}
// The last 1000 lines
const lines = output
.slice(Math.max(output.length - 1000, 1))
.map(this.renderEntry);
return (
<div className={className}>
<div className="output" ref={this.outputRef}>
{lines}
</div>
);
-128
View File
@@ -1,128 +0,0 @@
import * as React from 'react';
import * as tmp from 'tmp';
import * as fs from 'fs-extra';
import * as path from 'path';
import { observer } from 'mobx-react';
import { spawn, ChildProcess } from 'child_process';
import { normalizeVersion } from '../../utils/normalize-version';
import { AppState } from '../app';
import { findModules, installModules } from '../npm';
export interface RunnerState {
isRunning: boolean;
}
export interface RunnerProps {
appState: AppState;
}
@observer
export class Runner extends React.Component<RunnerProps, RunnerState> {
public child: ChildProcess | null = null;
constructor(props: RunnerProps) {
super(props);
this.run = this.run.bind(this);
this.pushData = this.pushData.bind(this);
this.stop = this.stop.bind(this);
this.state = {
isRunning: false
};
this.pushData('Console ready 🔬');
}
public render() {
const { versions, version } = this.props.appState;
const { isRunning } = this.state;
if (!versions || !version) return null;
const state = versions[normalizeVersion(version)].state;
let text = 'Run';
let action = this.run;
if (state === 'downloading') {
text = 'Downloading';
}
if (isRunning) {
text = 'Stop';
action = this.stop;
}
return <button className='button' onClick={() => action()}>{text}</button>;
}
public async stop() {
if (this.child) {
this.child.kill();
this.setState({
isRunning: false
});
}
}
public pushData(data: string | Buffer) {
const strData = data.toString();
if (strData.startsWith('Debugger listening on ws://')) return;
this.props.appState.output.push({
timestamp: Date.now(),
text: strData
});
}
public async installModules(values: any, dir: string) {
const files = [ values.main, values.renderer ];
const modules: Array<string> = [];
files.forEach((file) => {
modules.push(...findModules(file));
});
if (modules.length === 0) return;
this.pushData(`Installing npm modules: ${modules.join(', ')}...`);
this.pushData(await installModules({ dir }, ...modules));
}
public async run() {
const values = (window as any).electronFiddle.getValues();
const tmpdir = (tmp as any).dirSync();
const { binaryManager, version } = this.props.appState;
this.props.appState.isConsoleShowing = true;
try {
await fs.writeFile(path.join(tmpdir.name, 'index.html'), values.html);
await fs.writeFile(path.join(tmpdir.name, 'main.js'), values.main);
await fs.writeFile(path.join(tmpdir.name, 'renderer.js'), values.renderer);
await fs.writeFile(path.join(tmpdir.name, 'package.json'), values.package);
await this.installModules(values, tmpdir.name);
} catch (error) {
console.error('Could not write files', error);
}
if (!binaryManager.getIsDownloaded(version)) {
console.warn(`Binary ${version} not ready`);
return;
}
const binaryPath = this.props.appState.binaryManager.getElectronBinary(version);
console.log(`Binary ${binaryPath} ready, launching`);
this.child = spawn(binaryPath, [ tmpdir.name, '--inspect' ]);
this.setState({ isRunning: true });
this.pushData('Electron started.');
this.child.stdout.on('data', this.pushData);
this.child.stderr.on('data', this.pushData);
this.child.on('close', (code) => {
this.pushData(`Electron exited with code ${code.toString()}.`);
this.setState({ isRunning: false });
tmpdir.removeCallback();
});
}
}
@@ -0,0 +1,110 @@
import { Callout, Card } from '@blueprintjs/core';
import { shell } from 'electron';
import * as fs from 'fs-extra';
import * as path from 'path';
import * as React from 'react';
import { AppState } from '../state';
export interface CreditsSettingsProps {
appState: AppState;
}
export interface CreditsSettingsState {
contributors: Array<Contributor>;
}
export interface Contributor {
url: string;
api: string;
login: string;
avatar: string;
name: string;
bio: string;
location: string;
}
/**
* Settings content to manage Credits-related preferences.
*
* @class CreditsSettings
* @extends {React.Component<CreditsSettingsProps, CreditsSettingsState>}
*/
export class CreditsSettings extends React.Component<
CreditsSettingsProps,
CreditsSettingsState
> {
constructor(props: CreditsSettingsProps) {
super(props);
this.state = {
contributors: [],
};
this.getContributors();
}
/**
* Renders a list of contributors of Electron Fiddle.
*
* @returns {Array<JSX.Element>}
*/
public renderContributors(): Array<JSX.Element> {
const { contributors } = this.state;
return contributors.map(({ name, avatar, url, login, location, bio }) => {
const maybeLocation = location ? (
<p className="location">📍 {location}</p>
) : null;
const maybeBio = bio ? <small className="bio">{bio}</small> : null;
const style: React.CSSProperties = {
backgroundImage: `url(${avatar})`,
};
const onClick = () => shell.openExternal(url);
return (
<Card
interactive={true}
key={login}
className="contributor"
onClick={onClick}
>
<div className="avatar" style={style} />
<div className="details">
<h5 className="name">{name || login}</h5>
{maybeLocation}
{maybeBio}
</div>
</Card>
);
});
}
public render() {
return (
<div>
<h2>Credits</h2>
<Callout>
Electron Fiddle is, just like Electron, a free open source project
welcoming contributors of all genders, cultures, and backgrounds. We
would like to thank those who helped to make Electron Fiddle:
</Callout>
<br />
<div className="contributors">{this.renderContributors()}</div>
</div>
);
}
public async getContributors() {
try {
const contributorsFile = path.join(
__dirname,
'../../static/contributors.json',
);
const contributors = await fs.readJSON(contributorsFile);
this.setState({ contributors });
} catch (error) {
console.warn(`CreditsSettings: Fetching contributors failed`, error);
}
}
}
@@ -0,0 +1,402 @@
import {
Button,
ButtonGroup,
Callout,
Checkbox,
FormGroup,
HTMLTable,
IButtonProps,
Icon,
IconName,
Tooltip,
} from '@blueprintjs/core';
import { observer } from 'mobx-react';
import * as React from 'react';
import { RunnableVersion, VersionSource, VersionState } from '../../interfaces';
import { normalizeVersion } from '../../utils/normalize-version';
import { sortedElectronMap } from '../../utils/sorted-electron-map';
import { AppState } from '../state';
import { ElectronReleaseChannel, getReleaseChannel } from '../versions';
export interface ElectronSettingsProps {
appState: AppState;
}
export interface ElectronSettingsState {
isDownloadingAll: boolean;
isDeletingAll: boolean;
}
/**
* Settings content to manage Electron-related preferences.
*
* @class ElectronSettings
* @extends {React.Component<ElectronSettingsProps, {}>}
*/
@observer
export class ElectronSettings extends React.Component<
ElectronSettingsProps,
ElectronSettingsState
> {
constructor(props: ElectronSettingsProps) {
super(props);
this.handleDownloadAll = this.handleDownloadAll.bind(this);
this.handleDeleteAll = this.handleDeleteAll.bind(this);
this.handleChannelChange = this.handleChannelChange.bind(this);
this.handleStateChange = this.handleStateChange.bind(this);
this.handleDownloadClick = this.handleDownloadClick.bind(this);
this.handleAddVersion = this.handleAddVersion.bind(this);
this.state = {
isDownloadingAll: false,
isDeletingAll: false,
};
}
public handleDownloadClick() {
this.props.appState.updateElectronVersions();
}
/**
* Handles a change in which channels should be displayed.
*
* @param {React.ChangeEvent<HTMLInputElement>} event
*/
public handleStateChange(event: React.FormEvent<HTMLInputElement>) {
const { id, checked } = event.currentTarget;
const { appState } = this.props;
if (!checked) {
appState.statesToShow = appState.statesToShow.filter((s) => s !== id);
} else {
appState.statesToShow.push(id as VersionState);
}
}
/**
* Handles a change in which channels should be displayed.
*
* @param {React.ChangeEvent<HTMLInputElement>} event
*/
public handleChannelChange(event: React.FormEvent<HTMLInputElement>) {
const { id, checked } = event.currentTarget;
const { appState } = this.props;
if (!checked) {
appState.channelsToShow = appState.channelsToShow.filter((c) => c !== id);
} else {
appState.channelsToShow.push(id as ElectronReleaseChannel);
}
}
/**
* Download all versions of Electron.
*
* @returns {Promise<void>}
*/
public async handleDownloadAll(): Promise<void> {
this.setState({ isDownloadingAll: true });
const { versions, downloadVersion } = this.props.appState;
for (const key of Object.keys(versions)) {
await downloadVersion(key);
}
this.setState({ isDownloadingAll: false });
}
/**
* Delete all downloaded versions of Electron.
*
* @returns {Promise<void>}
*/
public async handleDeleteAll(): Promise<void> {
this.setState({ isDeletingAll: true });
const { versions, removeVersion, version } = this.props.appState;
for (const key in versions) {
// If this isn't the currently selected version, remove it
if (normalizeVersion(key) !== normalizeVersion(version)) {
await removeVersion(key);
}
}
this.setState({ isDeletingAll: false });
}
/**
* Opens the "add local version" dialog
*/
public handleAddVersion(): void {
this.props.appState.toggleAddVersionDialog();
}
public render() {
return (
<div className="settings-electron">
<h2>Electron Settings</h2>
<Callout>
{this.renderVersionChannelOptions()}
{this.renderVersionStateOptions()}
</Callout>
<br />
<Callout>
{this.renderAdvancedButtons()}
{this.renderTable()}
</Callout>
</div>
);
}
/**
* Renders the various buttons for advanced operations
*
* @private
* @returns {JSX.Element}
*/
private renderAdvancedButtons(): JSX.Element {
const { isDownloadingAll, isDeletingAll } = this.state;
const { isUpdatingElectronVersions } = this.props.appState;
const isWorking = isDownloadingAll || isDeletingAll;
return (
<ButtonGroup fill={true}>
<Button
disabled={isUpdatingElectronVersions}
onClick={this.handleDownloadClick}
loading={isUpdatingElectronVersions}
icon="numbered-list"
text="Update Electron Release List"
/>
<Button
disabled={isWorking}
icon="download"
onClick={this.handleDownloadAll}
text="Download All Versions"
/>
<Button
disabled={isWorking}
icon="trash"
onClick={this.handleDeleteAll}
text="Delete All Downloads"
/>
<Button
icon="document-open"
onClick={this.handleAddVersion}
text="Add Local Electron Build"
/>
</ButtonGroup>
);
}
/**
* Renders the various options for which versions should be displayed
* in the small dropdown.
*
* @private
* @returns {JSX.Element}
*/
private renderVersionStateOptions(): JSX.Element {
const { appState } = this.props;
const getIsChecked = (state: VersionState) => {
return appState.statesToShow.includes(state);
};
return (
<FormGroup label="Include Electron versions that are:">
<Tooltip content="Always enabled" position="bottom" intent="primary">
<Checkbox
checked={getIsChecked(VersionState.ready)}
label="Ready"
id="ready"
onChange={this.handleStateChange}
inline={true}
disabled={true}
/>
</Tooltip>
<Checkbox
checked={getIsChecked(VersionState.downloading)}
label="Downloading"
id="downloading"
onChange={this.handleStateChange}
inline={true}
/>
<Checkbox
checked={getIsChecked(VersionState.unknown)}
label="Not Downloaded"
id="unknown"
onChange={this.handleStateChange}
inline={true}
/>
</FormGroup>
);
}
/**
* Renders the various options for which versions should be displayed
*
* @private
* @returns {JSX.Element}
*/
private renderVersionChannelOptions(): JSX.Element {
const { appState } = this.props;
const getIsChecked = (channel: ElectronReleaseChannel) => {
return appState.channelsToShow.includes(channel);
};
const getIsCurrentVersionReleaseChannel = (
channel: ElectronReleaseChannel,
) => {
return getReleaseChannel(appState.version) === channel;
};
const channels = {
stable: ElectronReleaseChannel.stable,
beta: ElectronReleaseChannel.beta,
nightly: ElectronReleaseChannel.nightly,
unsupported: ElectronReleaseChannel.unsupported,
};
return (
<FormGroup label="Include Electron versions from these release channels:">
{Object.entries(channels).map(([_, channel]) => (
<Tooltip
content={`Can't disable channel of selected version (${appState.version})`}
disabled={!getIsCurrentVersionReleaseChannel(channel)}
position="bottom"
intent="primary"
key={channel}
>
<Checkbox
checked={getIsChecked(channel)}
label={channel}
id={channel}
onChange={this.handleChannelChange}
disabled={getIsCurrentVersionReleaseChannel(channel)}
inline={true}
/>
</Tooltip>
))}
</FormGroup>
);
}
/**
* Renders the table with Electron versions.
*
* @private
* @returns {JSX.Element}
*/
private renderTable(): JSX.Element {
return (
<HTMLTable className="electron-versions-table" striped={true}>
<thead>
<tr>
<th>Version</th>
<th>Status</th>
<th className="action">Action</th>
</tr>
</thead>
<tbody>{this.renderTableRows()}</tbody>
</HTMLTable>
);
}
/**
* Renders the rows with Electron version, returning an Arary.
*
* @private
* @returns {Array<JSX.Element>}
*/
private renderTableRows(): Array<JSX.Element | null> {
const { versions, channelsToShow, statesToShow } = this.props.appState;
return sortedElectronMap<JSX.Element | null>(versions, (key, item) => {
// Check if we want to show the version
if (!channelsToShow.includes(getReleaseChannel(item))) {
return null;
}
// Check if we want to show the state
if (!statesToShow.includes(item.state)) {
return null;
}
return (
<tr key={item.version}>
<td>{item.version}</td>
<td>{this.renderHumanState(item)}</td>
<td className="action">{this.renderAction(key, item)}</td>
</tr>
);
});
}
/**
* Returns a human-readable state indicator for an Electron version
*
* @param {RunnableVersion} item
* @returns {JSX.Element}
*/
private renderHumanState(item: RunnableVersion): JSX.Element {
const { state } = item;
let icon: IconName = 'box';
let humanState = 'Downloaded';
if (state === VersionState.downloading) {
icon = 'cloud-download';
humanState = 'Downloading';
} else if (state === VersionState.unknown) {
icon = 'cloud';
humanState = 'Not downloaded';
}
return (
<span>
<Icon icon={icon} /> {humanState}
</span>
);
}
/**
* Renders the action for a single Electron version
*
* @private
* @param {string} key
* @param {RunnableVersion} item
* @returns {JSX.Element}
*/
private renderAction(key: string, item: RunnableVersion): JSX.Element {
const { state, source } = item;
const { appState } = this.props;
const buttonProps: IButtonProps = {
fill: true,
small: true,
};
// Already downloaded
if (state === 'ready') {
buttonProps.onClick = () => appState.removeVersion(key);
buttonProps.icon = 'trash';
buttonProps.text = source === VersionSource.local ? 'Remove' : 'Delete';
} else if (state === 'downloading') {
buttonProps.disabled = true;
buttonProps.loading = true;
buttonProps.text = 'Downloading';
buttonProps.icon = 'cloud-download';
} else {
buttonProps.disabled = false;
buttonProps.loading = false;
buttonProps.text = 'Download';
buttonProps.icon = 'cloud-download';
buttonProps.onClick = () => appState.downloadVersion(key);
}
return <Button {...buttonProps} type={undefined} />;
}
}
@@ -0,0 +1,170 @@
import {
Callout,
Checkbox,
FormGroup,
InputGroup,
Radio,
RadioGroup,
} from '@blueprintjs/core';
import { observer } from 'mobx-react';
import * as React from 'react';
import { IPackageManager } from '../npm';
import { AppState } from '../state';
export interface ExecutionSettingsProps {
appState: AppState;
}
/**
* Settings content to manage execution-related preferences.
*
* @class ExecutionSettings
* @extends {React.Component<ExecutionSettingsProps, {}>}
*/
@observer
export class ExecutionSettings extends React.Component<ExecutionSettingsProps> {
constructor(props: ExecutionSettingsProps) {
super(props);
this.handleDeleteDataChange = this.handleDeleteDataChange.bind(this);
this.handleElectronLoggingChange = this.handleElectronLoggingChange.bind(
this,
);
this.handleExecutionFlagChange = this.handleExecutionFlagChange.bind(this);
}
/**
* Handles a change on whether or not the user data dir should be deleted
* after a run.
*
* @param {React.ChangeEvent<HTMLInputElement>} event
*/
public handleDeleteDataChange(event: React.FormEvent<HTMLInputElement>) {
const { checked } = event.currentTarget;
this.props.appState.isKeepingUserDataDirs = checked;
}
/**
* Handles a change on whether or not electron should log more things
*
* @param {React.ChangeEvent<HTMLInputElement>} event
*/
public handleElectronLoggingChange(event: React.FormEvent<HTMLInputElement>) {
const { checked } = event.currentTarget;
this.props.appState.isEnablingElectronLogging = checked;
}
/**
* Handles a change in the execution flags run with the Electron executable
*
* @param {React.ChangeEvent<HTMLInputElement>} event
*/
public handleExecutionFlagChange(event: React.FormEvent<HTMLInputElement>) {
const { value } = event.currentTarget;
const flags = value.split('|');
this.props.appState.executionFlags = flags;
}
public render() {
const {
isKeepingUserDataDirs,
isEnablingElectronLogging,
executionFlags = [],
} = this.props.appState;
const deleteUserDirLabel = `
Whenever Electron runs, it creates a user data directory for cookies, the cache,
and various other things that it needs to keep around. Since fiddles are usually
just run once, we delete this directory after your fiddle exits. Enable this
setting to keep the user data directories around.
`.trim();
const electronLoggingLabel = `
There are some flags that Electron uses to log extra information both internally
and through Chromium. Enable this option to make Fiddle produce those logs.`.trim();
return (
<div>
<h2>Execution</h2>
<Callout>
These advanced settings control how Electron Fiddle executes your
fiddles.
</Callout>
<br />
<Callout>
<FormGroup label={deleteUserDirLabel}>
<Checkbox
checked={isKeepingUserDataDirs}
label="Do not delete user data directories."
onChange={this.handleDeleteDataChange}
/>
</FormGroup>
</Callout>
<br />
<Callout>
<FormGroup label={electronLoggingLabel}>
<Checkbox
checked={isEnablingElectronLogging}
label="Enable advanced Electron logging."
onChange={this.handleElectronLoggingChange}
/>
</FormGroup>
</Callout>
<br />
<Callout>
<FormGroup>
<p>
Electron allows starting the executable with{' '}
<a href="https://www.electronjs.org/docs/api/command-line-switches">
user-provided flags
</a>
, such as &apos;--js-flags=--expose-gc&apos;. Those can be added
here as bar-separated (|) flags to run when you start your
Fiddles.
</p>
<br />
<InputGroup
placeholder="--js-flags=--expose-gc|--lang=es"
value={executionFlags.join('|')}
onChange={this.handleExecutionFlagChange}
/>
</FormGroup>
</Callout>
<br />
<Callout>
<FormGroup>
<span style={{ marginRight: 4 }}>
Electron Fiddle will install packages on runtime if they are
imported within your fiddle with <code>require</code>. It uses{' '}
<a href="https://www.npmjs.com/" target="_blank" rel="noreferrer">
npm
</a>{' '}
as its package manager by default, but{' '}
<a
href="https://classic.yarnpkg.com/lang/en/"
target="_blank"
rel="noreferrer"
>
Yarn
</a>{' '}
is also available.
</span>
<RadioGroup
onChange={this.handlePMChange}
selectedValue={this.props.appState.packageManager}
inline={true}
>
<Radio label="npm" value="npm" />
<Radio label="yarn" value="yarn" />
</RadioGroup>
</FormGroup>
</Callout>
</div>
);
}
private handlePMChange = (event: React.FormEvent<HTMLInputElement>) => {
this.props.appState.packageManager = event.currentTarget
.value as IPackageManager;
};
}
@@ -0,0 +1,235 @@
import { Button, Callout, FormGroup, MenuItem } from '@blueprintjs/core';
import { ItemPredicate, ItemRenderer, Select } from '@blueprintjs/select';
import { shell } from 'electron';
import * as fsType from 'fs-extra';
import { observer } from 'mobx-react';
import * as path from 'path';
import * as React from 'react';
import { highlightText } from '../../utils/highlight-text';
import { fancyImport } from '../../utils/import';
import { AppState } from '../state';
import { getAvailableThemes, getTheme, THEMES_PATH } from '../themes';
import { LoadedFiddleTheme } from '../themes-defaults';
const ThemeSelect = Select.ofType<LoadedFiddleTheme>();
/**
* Helper method: Returns the <Select /> predicate for an Electron
* version.
*
* @param {string} query
* @param {RunnableVersion} { version }
* @returns
*/
export const filterItem: ItemPredicate<LoadedFiddleTheme> = (
query,
{ name },
) => {
return name.toLowerCase().includes(query.toLowerCase());
};
/**
* Helper method: Returns the <Select /> <MenuItem /> for Electron
* versions.
*
* @param {RunnableVersion} item
* @param {IItemRendererProps} { handleClick, modifiers, query }
* @returns
*/
export const renderItem: ItemRenderer<LoadedFiddleTheme> = (
item,
{ handleClick, modifiers, query },
) => {
if (!modifiers.matchesPredicate) {
return null;
}
return (
<MenuItem
active={modifiers.active}
disabled={modifiers.disabled}
text={highlightText(item.name, query)}
key={item.name}
onClick={handleClick}
icon="media"
/>
);
};
export interface AppearanceSettingsProps {
appState: AppState;
toggleHasPopoverOpen: () => void;
}
export interface AppearanceSettingsState {
themes: Array<LoadedFiddleTheme>;
selectedTheme?: LoadedFiddleTheme;
}
/**
* Settings content to manage GitHub-related preferences.
*
* @class GitHubSettings
* @extends {React.Component<AppearanceSettingsProps, {}>}
*/
@observer
export class AppearanceSettings extends React.Component<
AppearanceSettingsProps,
AppearanceSettingsState
> {
public constructor(props: AppearanceSettingsProps) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.openThemeFolder = this.openThemeFolder.bind(this);
this.handleAddTheme = this.handleAddTheme.bind(this);
this.state = {
themes: [],
};
getAvailableThemes().then((themes) => {
const { theme } = this.props.appState;
const selectedTheme =
(theme && themes.find(({ file }) => file === theme)) || themes[0];
this.setState({ themes, selectedTheme });
});
this.createNewThemeFromCurrent = this.createNewThemeFromCurrent.bind(this);
this.openThemeFolder = this.openThemeFolder.bind(this);
}
/**
* Handle change, which usually means that we'd like update
* the current theme.
*
* @param {LoadedFiddleTheme} theme
*/
public handleChange(theme: LoadedFiddleTheme) {
this.setState({ selectedTheme: theme });
this.props.appState.setTheme(theme.file);
}
/**
* Creates a new theme from the current template.
*
* @returns {Promise<boolean>}
* @memberof AppearanceSettings
*/
public async createNewThemeFromCurrent(): Promise<boolean> {
const { appState } = this.props;
const fs = await fancyImport<typeof fsType>('fs-extra');
const theme = await getTheme(appState.theme);
try {
const namor = await fancyImport<any>('namor');
const name = namor.generate({ words: 2, numbers: 0 });
const themePath = path.join(THEMES_PATH, `${name}.json`);
await fs.outputJSON(
themePath,
{
...theme,
name,
file: undefined,
css: undefined,
},
{ spaces: 2 },
);
shell.showItemInFolder(themePath);
this.setState({ themes: await getAvailableThemes() });
return true;
} catch (error) {
console.warn(`Themes: Failed to create new theme from current`, error);
return false;
}
}
/**
* Creates the themes folder in .electron-fiddle if one does not
* exist yet, then shows that folder in the Finder/Explorer.
*
* @returns {Promise<boolean>}
*/
public async openThemeFolder(): Promise<boolean> {
const fs = await fancyImport<typeof fsType>('fs-extra');
try {
await fs.ensureDir(THEMES_PATH);
await shell.showItemInFolder(THEMES_PATH);
return true;
} catch (error) {
console.warn(`Appearance Settings: Could not open themes folder`);
return false;
}
}
public render() {
const { selectedTheme } = this.state;
const selectedName =
(selectedTheme && selectedTheme.name) || 'Select a theme';
return (
<div className="settings-appearance">
<h4>Appearance</h4>
<FormGroup label="Choose your theme" inline={true}>
<ThemeSelect
filterable={true}
items={this.state.themes}
itemRenderer={renderItem}
itemPredicate={filterItem}
onItemSelect={this.handleChange}
popoverProps={{
onClosed: () => this.props.toggleHasPopoverOpen(),
}}
noResults={<MenuItem disabled={true} text="No results." />}
>
<Button
id="open-theme-selector"
text={selectedName}
icon="tint"
onClick={() => this.props.toggleHasPopoverOpen()}
/>
</ThemeSelect>
</FormGroup>
<Callout>
<p>
To add themes, add JSON theme files to{' '}
<a id="open-theme-folder" onClick={this.openThemeFolder}>
<code>{THEMES_PATH}</code>
</a>
. The easiest way to get started is to clone one of the two existing
themes and to add your own colors.
</p>
<p>
Additionally, if you wish to import a Monaco Editor theme, pick your
JSON file and Fiddle will attempt to import it.
</p>
<Button
onClick={this.createNewThemeFromCurrent}
text="Create theme from current selection"
icon="duplicate"
/>
<Button
icon="document-open"
onClick={this.handleAddTheme}
text="Add a Monaco Editor theme"
/>
</Callout>
</div>
);
}
/**
* Opens the "add monaco theme" dialog
*/
public handleAddTheme(): void {
this.props.appState.toggleAddMonacoThemeDialog();
}
}
@@ -0,0 +1,58 @@
import { Callout, Checkbox, FormGroup } from '@blueprintjs/core';
import { observer } from 'mobx-react';
import * as React from 'react';
import { AppState } from '../state';
export interface ConsoleSettingsProps {
appState: AppState;
}
/**
* Settings content to manage console-related preferences.
*
* @class ConsoleSettings
* @extends {React.Component<ConsoleSettingsProps>}
*/
@observer
export class ConsoleSettings extends React.Component<ConsoleSettingsProps> {
constructor(props: ConsoleSettingsProps) {
super(props);
this.handleClearOnRunChange = this.handleClearOnRunChange.bind(this);
}
/**
* Handles a change on whether or not the console should be cleared
* before fiddle is executed.
*
* @param {React.ChangeEvent<HTMLInputElement>} event
*/
public handleClearOnRunChange(event: React.FormEvent<HTMLInputElement>) {
const { checked } = event.currentTarget;
this.props.appState.isClearingConsoleOnRun = checked;
}
public render() {
const { isClearingConsoleOnRun } = this.props.appState;
const clearOnRunLabel = `
Enable this option to automatically clear the console whenever you run your
fiddle.`.trim();
return (
<div>
<h4>Console</h4>
<Callout>
<FormGroup label={clearOnRunLabel}>
<Checkbox
checked={isClearingConsoleOnRun}
label="Clear on run."
onChange={this.handleClearOnRunChange}
/>
</FormGroup>
</Callout>
</div>
);
}
}
@@ -0,0 +1,84 @@
import { Button, Callout } from '@blueprintjs/core';
import { observer } from 'mobx-react';
import * as React from 'react';
import { AppState } from '../state';
export interface GitHubSettingsProps {
appState: AppState;
}
/**
* Settings content to manage GitHub-related preferences.
*
* @class GitHubSettings
* @extends {React.Component<GitHubSettingsProps, {}>}
*/
@observer
export class GitHubSettings extends React.Component<GitHubSettingsProps> {
constructor(props: GitHubSettingsProps) {
super(props);
this.signIn = this.signIn.bind(this);
}
/**
* Render the "logged out" settings experience.
*
* @returns {JSX.Element}
*/
public renderNotSignedIn(): JSX.Element {
return (
<Callout>
<p>
Your fiddles can be published as GitHub Gists - that way you can share
your fiddles with the world!
</p>
<Button onClick={this.signIn} icon="log-in" text="Sign in" />
</Callout>
);
}
/**
* Render the "logged in" settings experience.
*
* @returns {JSX.Element}
*/
public renderSignedIn(): JSX.Element {
const { gitHubLogin } = this.props.appState;
const signOut = this.props.appState.signOutGitHub;
return (
<Callout>
<p>
Your fiddles can be published as public GitHub Gists. Using the
personal access token you gave us, we logged you into GitHub as{' '}
<code>{gitHubLogin}</code>.
</p>
<Button onClick={signOut} icon="log-out" text="Sign out" />
</Callout>
);
}
public render() {
const { gitHubToken } = this.props.appState;
const maybeSignedIn = !!gitHubToken
? this.renderSignedIn()
: this.renderNotSignedIn();
return (
<div>
<h4>GitHub</h4>
{maybeSignedIn}
</div>
);
}
/**
* Simply shows the GitHub Token dialog.``
*/
private signIn() {
this.props.appState.isTokenDialogShowing = true;
}
}
@@ -0,0 +1,38 @@
import { Divider } from '@blueprintjs/core';
import { observer } from 'mobx-react';
import * as React from 'react';
import { AppState } from '../state';
import { AppearanceSettings } from './settings-general-appearance';
import { ConsoleSettings } from './settings-general-console';
import { GitHubSettings } from './settings-general-github';
export interface GeneralSettingsProps {
appState: AppState;
toggleHasPopoverOpen: () => void;
}
/**
* Settings content to manage GitHub-related preferences.
*
* @class GitHubSettings
* @extends {React.Component<GeneralSettingsProps>}
*/
@observer
export class GeneralSettings extends React.Component<GeneralSettingsProps> {
public render() {
return (
<div>
<h2>General Settings</h2>
<AppearanceSettings
appState={this.props.appState}
toggleHasPopoverOpen={() => this.props.toggleHasPopoverOpen()}
/>
<Divider />
<ConsoleSettings appState={this.props.appState} />
<Divider />
<GitHubSettings appState={this.props.appState} />
</div>
);
}
}
+179
View File
@@ -0,0 +1,179 @@
import { Icon, IconName, MenuItem } from '@blueprintjs/core';
import { observer } from 'mobx-react';
import * as React from 'react';
import { AppState } from '../state';
import { CreditsSettings } from './settings-credits';
import { ElectronSettings } from './settings-electron';
import { ExecutionSettings } from './settings-execution';
import { GeneralSettings } from './settings-general';
enum SettingsSections {
General = 'General',
Electron = 'Electron',
Execution = 'Execution',
Credits = 'Credits',
}
const settingsSections = [
SettingsSections.General,
SettingsSections.Electron,
SettingsSections.Execution,
SettingsSections.Credits,
];
export interface SettingsProps {
appState: AppState;
}
export interface SettingsState {
section: SettingsSections;
hasPopoverOpen: boolean;
}
/**
* Everything above the editors, so buttons and the address bar.
*
* @class Settings
* @extends {React.Component<SettingsProps, SettingsState>}
*/
@observer
export class Settings extends React.Component<SettingsProps, SettingsState> {
constructor(props: SettingsProps) {
super(props);
this.state = {
section: SettingsSections.General,
hasPopoverOpen: false,
};
this.closeSettingsPanel = this.closeSettingsPanel.bind(this);
}
public componentDidMount() {
window.addEventListener('keyup', this.closeSettingsPanel, true);
}
public componentWillUnmount() {
window.removeEventListener('keyup', this.closeSettingsPanel, true);
}
/**
* Renders the content of the settings, usually by simply
* return the appropriate component.
*
* @returns {(JSX.Element | null)}
*/
public renderContent(): JSX.Element | null {
const { section } = this.state;
const { appState } = this.props;
if (section === SettingsSections.General) {
return (
<GeneralSettings
appState={appState}
toggleHasPopoverOpen={() => this.toggleHasPopoverOpen()}
/>
);
}
if (section === SettingsSections.Electron) {
return <ElectronSettings appState={appState} />;
}
if (section === SettingsSections.Execution) {
return <ExecutionSettings appState={appState} />;
}
if (section === SettingsSections.Credits) {
return <CreditsSettings appState={appState} />;
}
return null;
}
/**
* Renders the individual menu items
*
* @returns {Array<JSX.Element>}
*/
public renderOptions(): Array<JSX.Element> {
const { section } = this.state;
return settingsSections.map((name) => {
const isSelected = section === name;
const onClick = () => this.setState({ section: name });
return (
<MenuItem
onClick={onClick}
active={isSelected}
key={name}
id={`settings-link-${name}`}
text={name}
icon={this.getIconForSection(name)}
/>
);
});
}
public render() {
const { appState } = this.props;
const { isSettingsShowing } = appState;
if (!isSettingsShowing) return null;
return (
<div className="settings">
<div className="settings-menu">
<ul>{this.renderOptions()}</ul>
</div>
<div className="settings-content">
<div className="settings-close" onClick={appState.toggleSettings}>
<Icon icon="cross" />
</div>
{this.renderContent()}
</div>
</div>
);
}
/**
* Get the settings icons
*
* @param {SettingsSections} section
* @memberof Settings
*/
private getIconForSection(section: SettingsSections): IconName {
if (section === SettingsSections.Credits) {
return 'heart';
} else if (section === SettingsSections.Electron) {
return 'floppy-disk';
} else if (section === SettingsSections.Execution) {
return 'play';
}
return 'cog';
}
/**
* Trigger closing of the settings panel upon Esc
* If hasPopoverOpen is set to true, settings will not close as only the popover should close
*/
private closeSettingsPanel(event: KeyboardEvent) {
const { appState } = this.props;
if (event.code === 'Escape' && !this.state.hasPopoverOpen) {
appState.isSettingsShowing = false;
}
}
/**
* Toggles whether there is a popover open
*/
public toggleHasPopoverOpen(): void {
this.setState({
...this.state,
hasPopoverOpen: !this.state.hasPopoverOpen,
});
}
}
+31
View File
@@ -0,0 +1,31 @@
import { observer } from 'mobx-react';
import * as React from 'react';
import { AppState } from '../state';
import { DOCS_DEMO_COMPONENTS } from './show-me/index';
export interface ShowMeProps {
appState: AppState;
}
/**3
* The root component for "show me" content - the fourth helpful
* panel.
*
* @class ShowMe
* @extends {React.Component<ShowMeProps>}
*/
@observer
export class ShowMe extends React.Component<ShowMeProps> {
public render() {
const { currentDocsDemoPage: showMeName } = this.props.appState;
const Content =
DOCS_DEMO_COMPONENTS[showMeName] || DOCS_DEMO_COMPONENTS.DEFAULT;
return (
<div className="show-me-panel">
<Content appState={this.props.appState} />
</div>
);
}
}
+141
View File
@@ -0,0 +1,141 @@
import * as React from 'react';
import { Button, Callout, Icon } from '@blueprintjs/core';
import { remote } from 'electron';
import { renderMoreDocumentation } from './more-information';
import { getSubsetOnly } from './subset-only';
/**
* Show and hide button examples, only rendered on macOS
*
* @returns {JSX.Element | null}
*/
function ShowHide() {
if (process.platform !== 'darwin') return null;
const onClick = () => {
remote.app.hide();
setTimeout(() => {
remote.app.show();
remote.app.focus();
}, 1500);
};
return (
<>
<p>
This button hides Electron Fiddle right away, showing it again in two
seconds.
</p>
<Button
id="show-hide"
icon="eye-off"
text="Hide Electron Fiddle"
onClick={onClick}
/>
</>
);
}
export function ShowMeApp(): JSX.Element {
const [secondsLeft, setSeconds] = React.useState(-1);
const playFocus = () => {
setSeconds(3);
setTimeout(() => setSeconds(2), 1000);
setTimeout(() => setSeconds(1), 2000);
setTimeout(() => {
remote.app.focus();
setSeconds(-1);
}, 3000);
};
const [paths, setPaths] = React.useState('');
const playPaths = () => {
const pathsToQuery = [
'home',
'appData',
'userData',
'temp',
'downloads',
'desktop',
];
let result = '';
pathsToQuery.forEach((item) => {
result += `${item}: ${remote.app.getPath(item as any)}\n`;
});
setPaths(result);
};
const [metrics, setMetrics] = React.useState('');
const playMetrics = () => {
setMetrics(JSON.stringify(remote.app.getAppMetrics(), undefined, 2));
};
return (
<>
<Icon
icon="help"
iconSize={40}
style={{ float: 'left', margin: '0 10px 0 0' }}
/>
<p className="bp3r-running-text">
The <code>app</code> module controls the app&apos;s application
life-cycle. Most of the events and methods available on this module are
responsible for handling how your interacts with the operating system or
to set application-wide settings.
</p>
<h3>API Demos</h3>
{getSubsetOnly('app')}
<Callout title="Hiding, Showing, Focussing" icon="eye-open">
<p>
The app can ask the operating system for window focus. On macOS, it
can additionally request that the app be hidden or shown. Give it a
try: Click on the button below, focus another app, and wait for two
seconds to see Electron Fiddle become the focused app again.
</p>
<Button
id="focus"
icon="lightbulb"
text={`Focus Electron Fiddle${
secondsLeft > 0 ? ` in ${secondsLeft}s` : ''
}`}
onClick={playFocus}
/>
<ShowHide />
</Callout>
<Callout title="Paths" icon="folder-open">
<p>
Need to query information about various paths in a cross-platform
manner? Electron can help. The button queries the operating system for
some of them.
</p>
<Button
id="special-paths"
icon="play"
text={`Get special directory paths`}
onClick={playPaths}
/>
<pre id="special-paths-content">{paths}</pre>
</Callout>
<Callout title="Process & Device Information" icon="pulse">
<p>
Need to query information about the process or system? The{' '}
<code>app</code> module lets developers query for information about
the running app, hardware, and operating system. A good example are
process metrics.
</p>
<Button
id="process-metrics"
icon="play"
text={`Get process metrics`}
onClick={playMetrics}
/>
<pre id="process-metrics-content">{metrics}</pre>
</Callout>
{renderMoreDocumentation()}
</>
);
}
@@ -0,0 +1,47 @@
import { Button, Icon } from '@blueprintjs/core';
import * as React from 'react';
import { DocsDemoPage } from '../../../interfaces';
import { AppState } from '../../state';
import { DOCS_DEMO_COMPONENTS, DOCS_DEMO_NAMES } from './index';
import { renderMoreDocumentation } from './more-information';
export function ShowMeDefault(props: { appState: AppState }): JSX.Element {
const showMeMenu: Array<JSX.Element> = Object.keys(DOCS_DEMO_COMPONENTS)
.filter((key) => key !== DocsDemoPage.DEFAULT)
.map((key) => {
return (
<li key={key}>
<Button
minimal={true}
icon="play"
text={DOCS_DEMO_NAMES[key]}
onClick={() =>
(props.appState.currentDocsDemoPage = key as DocsDemoPage)
}
/>
</li>
);
});
return (
<>
<Icon
icon="help"
iconSize={40}
style={{ float: 'left', margin: '0 10px 0 0' }}
/>
<p className="bp3r-running-text">
This panel offers useful information about Electron APIs  and easy way
to try some of the methods it offers. Fiddle has an example fiddle for
every module available in Electron.
</p>
<p>
Clicking on any of the modules below will open up a fiddle showcasing
that particular module.
</p>
<ul className="show-me-list">{...showMeMenu}</ul>
{renderMoreDocumentation()}
</>
);
}
+14
View File
@@ -0,0 +1,14 @@
import { DocsDemoPage } from '../../../interfaces';
import { ShowMeApp } from './app';
import { ShowMeDefault } from './default';
export const DOCS_DEMO_COMPONENTS: Record<DocsDemoPage, any> = {
DEFAULT: ShowMeDefault,
DEMO_APP: ShowMeApp,
};
export const DOCS_DEMO_NAMES: Record<DocsDemoPage, string> = {
DEFAULT: 'Home',
DEMO_APP: 'App Demos',
};

Some files were not shown because too many files have changed in this diff Show More