Compare commits

...

823 Commits

Author SHA1 Message Date
renovate[bot]
f3a043b0a4 chore(deps): update actions/setup-node action to v6 2026-03-27 05:11:48 +00:00
renovate[bot]
0a2ea1e09d chore(deps): update dependency @babel/core to v7.29.0 (#2504)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-27 01:29:47 +00:00
renovate[bot]
be77363515 chore(deps): update babel monorepo to v7.28.6 (#2501)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-15 05:51:38 +00:00
renovate[bot]
b1a1c5c01b chore(deps): update babel monorepo to v7.28.5 (#2494)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-28 03:47:34 +00:00
renovate[bot]
6b60360ce1 chore(deps): update babel monorepo to v7.28.4 (#2488)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-06 16:07:58 +00:00
renovate[bot]
56e92101b0 chore(deps): update babel monorepo to v7.28.3 (#2487)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-15 12:46:15 +00:00
renovate[bot]
2a5c67f9e3 fix(deps): update dependency @electron/remote to v2.1.3 (#2485)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-08 21:13:11 +00:00
renovate[bot]
ef39f41e96 chore(deps): update babel monorepo to v7.28.0 (#2484)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-03 13:11:16 +00:00
renovate[bot]
d317ea3ff8 chore(deps): update dependency @babel/core to v7.27.7 (#2482)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-27 15:49:04 +00:00
renovate[bot]
787e4c441b chore(deps): update dependency @babel/eslint-parser to v7.27.5 (#2480)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-04 16:06:08 +00:00
renovate[bot]
ef116d01b7 chore(deps): update dependency @babel/core to v7.27.4 (#2479)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-31 17:03:45 +00:00
renovate[bot]
0a5be1f166 chore(deps): update dependency @babel/core to v7.27.3 (#2478)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-28 09:28:35 +00:00
renovate[bot]
4a35518da7 chore(deps): update dependency @babel/cli to v7.27.2 (#2475)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-07 20:22:11 +00:00
renovate[bot]
8f3301cd1e chore(deps): update babel monorepo to v7.27.1 (#2474)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-01 17:29:51 +00:00
renovate[bot]
97b10558f6 chore(deps): update babel monorepo (#2466)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-27 12:10:52 +00:00
renovate[bot]
e61501f13f chore(deps): update babel monorepo (#2459)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-18 21:49:47 +00:00
renovate[bot]
b1d1778479 chore(deps): update dependency @babel/eslint-parser to v7.26.5 (#2457)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-15 14:14:09 +00:00
renovate[bot]
9cca2d39c3 chore(deps): update babel monorepo (#2453)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-08 21:05:11 +00:00
renovate[bot]
fcee4017d7 chore(deps): update dependency tape to v5.9.0 2024-10-16 06:34:29 +00:00
renovate[bot]
2890419d6d chore(deps): update babel monorepo 2024-10-16 05:21:16 +00:00
renovate[bot]
0fe3dd977f chore(deps): update dependency @babel/cli to v7.25.6 2024-08-30 13:58:05 +00:00
renovate[bot]
9ba088f76f chore(deps): update dependency electron-winstaller to v5.4.0 2024-08-12 11:46:38 +00:00
renovate[bot]
1a7404ee8a chore(deps): update babel monorepo 2024-08-12 11:31:09 +00:00
renovate[bot]
f1de7606a5 chore(deps): update npm to v10 (#2426)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-12 13:28:56 +02:00
Borewit
d4b493cebe Fix CI shield in README (#2437)
Replace deprecated Travis shield with GitHub Action CI shield
2024-08-12 13:24:03 +02:00
renovate[bot]
1df3d025bd chore(deps): update babel monorepo 2024-07-21 17:27:22 +00:00
renovate[bot]
61b7681fd1 chore(deps): update dependency tape to v5.8.1 2024-06-17 18:50:56 +00:00
renovate[bot]
ac7f16e71c chore(deps): update dependency tape to v5.8.0 2024-06-16 04:07:26 +00:00
renovate[bot]
b363dca77f chore(deps): update dependency electron-winstaller to v5.3.1 2024-06-09 19:36:43 +00:00
renovate[bot]
16cabd19ff chore(deps): update dependency electron to v27.3.11 2024-06-09 15:22:50 +00:00
renovate[bot]
390b4ad7ec chore(deps): update babel monorepo to v7.24.7 2024-06-09 12:08:50 +00:00
renovate[bot]
b3dc3292b7 chore(deps): update dependency electron-winstaller to v5.3.0 2024-04-02 19:13:47 +00:00
renovate[bot]
244a242bdc chore(deps): update dependency electron to v27.3.8 2024-04-02 16:20:07 +00:00
renovate[bot]
241f3cb9a3 chore(deps): update babel monorepo 2024-04-02 16:17:23 +00:00
Herwig Hochleitner
aa4fb3d08e chore(deps): Upgrade to Electron v27 (#2388) 2024-04-02 18:14:50 +02:00
renovate[bot]
ebaf9cf848 fix(deps): update dependency music-metadata to v7.14.0 2024-02-26 01:21:30 +00:00
renovate[bot]
df05db5583 fix(deps): update dependency @electron/remote to v2.1.2 2024-02-25 22:28:16 +00:00
renovate[bot]
1ccfa404d2 chore(deps): update dependency tape to v5.7.5 2024-02-25 19:37:03 +00:00
renovate[bot]
bc19caf8ee chore(deps): update dependency electron-winstaller to v5.2.2 2024-02-25 15:50:03 +00:00
renovate[bot]
36c24a4940 chore(deps): update babel monorepo 2024-02-25 12:07:37 +00:00
renovate[bot]
1cefcff3da chore(deps): update dependency depcheck to v1.4.7 2023-12-20 00:09:20 +00:00
renovate[bot]
1eb61201d6 chore(deps): update dependency electron-installer-debian to v3.2.0 2023-09-07 03:37:53 +00:00
renovate[bot]
3e514f9cf6 fix(deps): update dependency @electron/remote to v2.0.11 2023-09-07 01:35:26 +00:00
renovate[bot]
b8f1d950f2 chore(deps): update dependency depcheck to v1.4.5 2023-09-06 22:04:13 +00:00
renovate[bot]
a85effc8ec chore(deps): update babel monorepo to v7.22.15 2023-09-06 22:01:22 +00:00
renovate[bot]
cf846979b0 chore(deps): update babel monorepo to v7.22.10 2023-08-08 20:16:46 +00:00
renovate[bot]
9f630c9bfb chore(deps): update dependency tape to v5.6.6 2023-07-19 23:16:44 +00:00
renovate[bot]
1d66b6d069 chore(deps): update dependency tape to v5.6.5 2023-07-13 22:50:50 +00:00
renovate[bot]
6b83ed34b9 chore(deps): update babel monorepo to v7.22.9 2023-07-13 18:39:30 +00:00
renovate[bot]
a0aeae7e91 chore(deps): update dependency plist to v3.1.0 2023-07-07 20:28:35 +00:00
renovate[bot]
99e3058676 chore(deps): update babel monorepo 2023-07-07 15:29:59 +00:00
renovate[bot]
20d1d8a224 chore(deps): update babel monorepo to v7.22.6 2023-07-05 12:31:07 +00:00
renovate[bot]
0b34ff1148 chore(deps): update dependency tape to v5.6.4 2023-07-03 07:26:03 +00:00
renovate[bot]
4120fcf4af chore(deps): update babel monorepo to v7.22.5 2023-06-14 12:29:59 +00:00
renovate[bot]
7ea277ccf6 fix(deps): update dependency @electron/remote to v2.0.10 2023-06-07 00:00:55 +00:00
renovate[bot]
77a981178b chore(deps): update dependency @babel/plugin-transform-react-jsx to v7.22.3 2023-05-28 14:03:53 +00:00
renovate[bot]
ea19545ec6 chore(deps): update dependency @babel/core to v7.22.1 2023-05-27 19:28:13 +00:00
renovate[bot]
6f6ccb029c chore(deps): update babel monorepo to v7.22.0 2023-05-27 15:44:47 +00:00
renovate[bot]
43b2d28fb5 chore(deps): update babel monorepo to v7.21.8 2023-05-03 21:19:42 +00:00
renovate[bot]
f20d24ac3c chore(deps): update babel monorepo to v7.21.5 2023-04-30 02:00:10 +00:00
renovate[bot]
b1332ee76b chore(deps): update dependency @babel/core to v7.21.4 2023-04-01 15:08:16 +00:00
renovate[bot]
34b8f3fb64 fix(deps): update dependency music-metadata to v7.13.4 2023-03-30 20:52:34 +00:00
renovate[bot]
b4f98e91ff chore(deps): update dependency nodemon to v2.0.22 2023-03-23 22:26:52 +00:00
renovate[bot]
ebb8d23ef3 chore(deps): update dependency gh-release to v7 (#2301)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-16 14:23:49 +01:00
renovate[bot]
e5bf6745bf chore(deps): update dependency pngjs to v7 (#2326)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-16 14:14:54 +01:00
renovate[bot]
686f63b35f fix(deps): update dependency rimraf to v4 (#2328)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-16 14:09:44 +01:00
renovate[bot]
4ed5f3ff5f chore(deps): update dependency appdmg to v0.6.6 (#2318)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Alex <alxmorais8@msn.com>
2023-03-16 14:01:51 +01:00
dependabot[bot]
af8379012a build(deps): bump http-cache-semantics from 4.1.0 to 4.1.1 (#2313)
Bumps [http-cache-semantics](https://github.com/kornelski/http-cache-semantics) from 4.1.0 to 4.1.1.
- [Release notes](https://github.com/kornelski/http-cache-semantics/releases)
- [Commits](https://github.com/kornelski/http-cache-semantics/compare/v4.1.0...v4.1.1)

---
updated-dependencies:
- dependency-name: http-cache-semantics
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-16 13:58:45 +01:00
renovate[bot]
1c53102e12 chore(deps): update dependency minimist to v1.2.8 (#2319)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-16 13:52:55 +01:00
renovate[bot]
1a074b65e6 chore(deps): update dependency open to v8.4.2 (#2321)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-16 13:42:26 +01:00
renovate[bot]
2052adde7d chore(deps): update dependency electron-installer-redhat to v3.4.0 2023-03-16 12:37:17 +00:00
renovate[bot]
eed9eebd45 fix(deps): update dependency webtorrent to v1.9.7 2023-03-16 12:31:43 +00:00
renovate[bot]
e36eacd05a fix(deps): update dependency music-metadata to v7.13.3 2023-03-16 12:26:12 +00:00
renovate[bot]
9c7cffa1a3 chore(deps): update dependency tape to v5.6.3 2023-03-16 12:20:53 +00:00
renovate[bot]
94d2bd7807 chore(deps): update dependency nodemon to v2.0.21 2023-03-16 12:15:21 +00:00
renovate[bot]
5efbf7e5c9 chore(deps): update babel monorepo 2023-03-16 12:10:29 +00:00
renovate[bot]
fce078defe fix(deps): update dependency music-metadata to v7.13.1 2023-01-06 17:32:19 +00:00
renovate[bot]
10f355ba0f chore(deps): update dependency @babel/core to v7.20.12 2023-01-05 19:46:05 +00:00
renovate[bot]
9d8293b970 chore(deps): update babel monorepo to v7.20.7 2022-12-23 12:23:19 +00:00
renovate[bot]
73b8b54ae8 fix(deps): update dependency @electron/remote to v2.0.9 2022-12-07 02:25:28 +00:00
renovate[bot]
bc49dbc41d fix(deps): update dependency webtorrent to v1.9.6 2022-12-04 00:00:17 +00:00
renovate[bot]
69b1ff58d0 chore(deps): update dependency @babel/core to v7.20.5 2022-11-29 15:34:34 +00:00
renovate[bot]
cf48311fcb fix(deps): update dependency webtorrent to v1.9.4 2022-11-21 14:56:21 +00:00
renovate[bot]
c919af1fd9 fix(deps): update dependency webtorrent to v1.9.3 2022-11-19 00:57:08 +00:00
dependabot[bot]
cdc5ac6538 build(deps): bump loader-utils from 1.4.0 to 1.4.2 (#2288)
Bumps [loader-utils](https://github.com/webpack/loader-utils) from 1.4.0 to 1.4.2.
- [Release notes](https://github.com/webpack/loader-utils/releases)
- [Changelog](https://github.com/webpack/loader-utils/blob/v1.4.2/CHANGELOG.md)
- [Commits](https://github.com/webpack/loader-utils/compare/v1.4.0...v1.4.2)

---
updated-dependencies:
- dependency-name: loader-utils
  dependency-type: indirect
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-11 15:04:46 +01:00
renovate[bot]
05881478b5 fix(deps): update dependency webtorrent to v1.9.2 2022-11-11 05:52:42 +00:00
renovate[bot]
fb279010d0 chore(deps): update dependency electron-winstaller to v5.1.0 (#2277)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-11 01:10:49 +01:00
renovate[bot]
e54f61c480 fix(deps): update dependency create-torrent to v5.0.9 (#2287)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-11 01:00:56 +01:00
renovate[bot]
ab9468f84f chore(deps): update npm to v9 (#2283)
* chore(deps): update npm to v9

* Update package.json

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Diego Rodríguez Baquero <diego@protocol.ai>
2022-11-10 15:15:19 -05:00
renovate[bot]
0f20c0acd1 chore(deps): update dependency @babel/core to v7.20.2 2022-11-06 00:06:21 +00:00
renovate[bot]
a4ef6cb562 fix(deps): update dependency webtorrent to v1.9.1 2022-10-28 16:53:40 +00:00
renovate[bot]
21c260dc13 chore(deps): update dependency electron-notarize to v1.2.2 2022-10-22 01:44:22 +00:00
renovate[bot]
0df520c5ba chore(deps): update dependency @babel/core to v7.19.6 2022-10-21 12:02:18 +00:00
renovate[bot]
707461a264 chore(deps): update dependency minimist to v1.2.7 (#2271)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-15 16:35:45 +02:00
renovate[bot]
a22f94df80 fix(deps): update dependency semver to v7.3.8 (#2268)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-09 12:05:24 +02:00
renovate[bot]
a60e817e0c fix(deps): update dependency webtorrent to v1.8.32 2022-10-09 07:34:24 +00:00
renovate[bot]
f1865dda4f fix(deps): update dependency webtorrent to v1.8.31 2022-10-09 02:35:05 +00:00
renovate[bot]
8cdc6b1307 chore(deps): update dependency spectron to v19 (#2133)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Alex <alxmorais8@msn.com>
2022-10-01 16:31:12 +02:00
dependabot[bot]
660facf8c2 build(deps): bump jsonpointer and is-my-json-valid (#2264)
Bumps [jsonpointer](https://github.com/janl/node-jsonpointer) and [is-my-json-valid](https://github.com/mafintosh/is-my-json-valid). These dependencies needed to be updated together.

Updates `jsonpointer` from 4.1.0 to 5.0.1
- [Release notes](https://github.com/janl/node-jsonpointer/releases)
- [Commits](https://github.com/janl/node-jsonpointer/compare/v4.1.0...v5.0.1)

Updates `is-my-json-valid` from 2.20.5 to 2.20.6
- [Release notes](https://github.com/mafintosh/is-my-json-valid/releases)
- [Commits](https://github.com/mafintosh/is-my-json-valid/compare/v2.20.5...v2.20.6)

---
updated-dependencies:
- dependency-name: jsonpointer
  dependency-type: indirect
- dependency-name: is-my-json-valid
  dependency-type: indirect
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Alex <alxmorais8@msn.com>
2022-10-01 12:08:04 +02:00
renovate[bot]
fee5b42813 chore(deps): update actions/stale action to v6 (#2259)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-10-01 12:03:49 +02:00
renovate[bot]
ddb8500082 chore(deps): update babel monorepo to v7.19.3 2022-09-28 18:55:54 +00:00
renovate[bot]
cc6af9829e chore(deps): update dependency tape to v5.6.1 2022-09-20 23:51:15 +00:00
renovate[bot]
cfba6b503a fix(deps): update dependency music-metadata to v7.13.0 2022-09-19 12:15:21 +00:00
renovate[bot]
04c766bb53 chore(deps): update dependency nodemon to v2.0.20 2022-09-17 13:23:51 +00:00
renovate[bot]
2389a1aa35 chore(deps): update babel monorepo to v7.19.1 2022-09-15 17:58:20 +00:00
renovate[bot]
430b4c409a fix(deps): update dependency webtorrent to v1.8.30 2022-09-12 22:50:38 +00:00
renovate[bot]
810952f234 chore(deps): update babel monorepo to v7.19.0 2022-09-07 01:54:36 +00:00
renovate[bot]
ae4a8e40f8 fix(deps): update dependency webtorrent to v1.8.29 2022-09-03 10:27:11 +00:00
renovate[bot]
ea100dda36 fix(deps): update webtorrent 2022-09-03 01:22:01 +00:00
Diego Rodríguez Baquero
46cbce00ca Update stale.yml 2022-09-02 11:07:08 -05:00
dependabot[bot]
00ebbc7e17 build(deps): bump protobufjs from 6.10.2 to 6.11.3 (#2214)
Bumps [protobufjs](https://github.com/protobufjs/protobuf.js) from 6.10.2 to 6.11.3.
- [Release notes](https://github.com/protobufjs/protobuf.js/releases)
- [Changelog](https://github.com/protobufjs/protobuf.js/blob/v6.11.3/CHANGELOG.md)
- [Commits](https://github.com/protobufjs/protobuf.js/compare/v6.10.2...v6.11.3)

---
updated-dependencies:
- dependency-name: protobufjs
  dependency-type: indirect
...

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-28 18:48:05 +02:00
renovate[bot]
8109ce5410 fix(deps): update dependency iso-639-1 to v2.1.15 (#2213)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-08-28 00:24:16 +02:00
renovate[bot]
9200070269 chore(deps): update dependency electron-packager to v15.5.2 2022-08-24 03:23:12 +00:00
renovate[bot]
16ab96e4ac chore(deps): update dependency @babel/core to v7.18.13 2022-08-23 19:04:25 +00:00
renovate[bot]
d8632f6386 chore(deps): update dependency tape to v5.6.0 2022-08-17 22:07:38 +00:00
renovate[bot]
5558bad0de fix(deps): update dependency music-metadata to v7.12.6 2022-08-05 12:27:45 +00:00
renovate[bot]
0f5b7fd80e chore(deps): update babel monorepo to v7.18.10 2022-08-02 19:54:53 +00:00
renovate[bot]
6a288efb57 fix(deps): update dependency music-metadata to v7.12.5 2022-07-25 10:26:40 +00:00
renovate[bot]
f07a307b0d chore(deps): update babel monorepo to v7.18.9 2022-07-19 11:40:08 +00:00
renovate[bot]
cb1de722fe chore(deps): update dependency plist to v3.0.6 2022-07-13 22:41:20 +00:00
renovate[bot]
45036451c7 chore(deps): update dependency nodemon to v2.0.19 2022-07-06 17:13:24 +00:00
renovate[bot]
58a4f7a34a fix(deps): update dependency music-metadata to v7.12.4 2022-07-05 12:43:25 +00:00
renovate[bot]
9082c6f63e fix(deps): update dependency webtorrent to v1.8.26 2022-07-04 02:50:37 +00:00
renovate[bot]
9fb8a2ae09 fix(deps): update webtorrent 2022-07-04 02:42:36 +00:00
renovate[bot]
0e501b498e fix(deps): update dependency create-torrent to v5.0.3 2022-07-03 19:35:47 +00:00
renovate[bot]
85e0c5709e chore(deps): update babel monorepo to v7.18.6 2022-06-28 19:52:17 +00:00
renovate[bot]
cee88a7e24 chore(deps): update dependency nodemon to v2.0.18 2022-06-24 15:37:09 +00:00
renovate[bot]
f503a46447 fix(deps): update dependency webtorrent to v1.8.24 2022-06-24 05:42:10 +00:00
renovate[bot]
1cdd54e421 fix(deps): update dependency webtorrent to v1.8.23 2022-06-23 05:47:20 +00:00
Renovate Bot
73be2513ad chore(deps): update dependency @babel/core to v7.18.5 2022-06-14 12:06:06 +00:00
Renovate Bot
e9eb22a530 chore(deps): update babel monorepo to v7.18.2 2022-05-26 11:32:46 +00:00
Renovate Bot
d17f287ba2 chore(deps): update dependency electron to v15.5.7 2022-05-25 20:03:10 +00:00
Renovate Bot
06b904b837 fix(deps): update dependency webtorrent to v1.8.22 2022-05-24 05:20:44 +00:00
Renovate Bot
807c6aebdd chore(deps): update dependency @babel/core to v7.18.0 2022-05-20 20:27:48 +00:00
Renovate Bot
ab54a7cfb3 chore(deps): update babel monorepo to v7.17.12 2022-05-17 20:07:55 +00:00
Renovate Bot
77d4eed9fc fix(deps): update dependency webtorrent to v1.8.20 2022-05-14 04:56:53 +00:00
Diego Rodriguez Baquero
9c73638d1b fix: standard 2022-05-13 17:15:56 -05:00
Alex Lavallee
3dd7ebb34b feat(Player Page): Add support for mediaSession (#2170)
* feat(Player Page): Add support for mediaSession

* Update player-page.js
2022-05-11 18:44:43 -05:00
Subin Siby
c943f39f6b feat: add preference to customize global trackers (#1836)
* Add preference to customize global trackers. Requires restart to apply

* Use IPC to pass global trackers list, torrent pause and resume will now update trackers

* Make the default tracker list an array from array of arrays

* Use globalThis instead of just global

Co-authored-by: Diego Rodríguez Baquero <github@diegorbaquero.com>
2022-05-11 18:43:54 -05:00
CommanderRoot
401698e616 refactor: replace deprecated String.prototype.substr() (#2173)
.substr() is deprecated so we replace it with .slice() which works similarily but isn't deprecated

Signed-off-by: Tobias Speicher <rootcommander@gmail.com>
2022-05-11 18:41:56 -05:00
Christopher Toth
c85b3e4fd1 feat(a11y): Added roles and labels to the playback controls (#2167) 2022-05-11 18:40:43 -05:00
renovate[bot]
be15ee073d chore(deps): update dependency electron to v15.5.5 (#2204)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-11 18:39:01 -05:00
renovate[bot]
d838e6276d chore(deps): update babel monorepo to v7.17.10 (#2203)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-11 18:38:43 -05:00
renovate[bot]
35af086fad chore(deps): update dependency electron-packager to v15.5.1 (#2197)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-11 18:38:31 -05:00
renovate[bot]
cf9fbf2b0e fix(deps): update dependency semver to v7.3.7 (#2192)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-11 18:38:09 -05:00
renovate[bot]
ef2225c8a5 fix(deps): update dependency bitfield to v4.1.0 (#2201)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-11 18:37:22 -05:00
renovate[bot]
ffacb6085d chore(deps): update dependency nodemon to v2.0.16 (#2202)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-11 18:37:00 -05:00
renovate[bot]
20a84359cd chore(deps): update dependency standard to v17 (#2198)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-11 18:33:58 -05:00
renovate[bot]
a3d123537f fix(deps): update dependency webtorrent to v1.8.19 (#2200)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-11 18:21:13 -05:00
Renovate Bot
30fb222fb9 chore(deps): update dependency gh-release to v6.0.4 2022-04-16 00:08:23 +00:00
Renovate Bot
4c2a08dd52 chore(deps): update dependency tape to v5.5.3 2022-04-09 20:19:02 +00:00
Renovate Bot
406c568c1e chore(deps): update dependency electron to v15.5.2 2022-04-07 21:01:30 +00:00
Renovate Bot
a86424b7df chore(deps): update dependency @babel/core to v7.17.9 2022-04-07 17:13:51 +00:00
Renovate Bot
f6ffc16964 fix(deps): update dependency music-metadata to v7.12.3 2022-04-02 19:49:42 +00:00
Renovate Bot
05e8a0d284 chore(deps): update dependency electron to v15.5.1 2022-03-31 18:17:15 +00:00
Renovate Bot
1dc38afc85 fix(deps): update dependency webtorrent to v1.8.13 2022-03-31 04:44:02 +00:00
renovate[bot]
ca73b3c286 chore(deps): update actions/cache action to v3 (#2171)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-30 12:21:51 +03:00
renovate[bot]
bad30e8f1a chore(deps): update dependency minimist to v1.2.6 (#2172)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-30 12:21:22 +03:00
Renovate Bot
56036e89af chore(deps): update dependency electron to v15.5.0 2022-03-30 02:28:31 +00:00
Renovate Bot
bb7a9bb018 fix(deps): update dependency webtorrent to v1.8.12 2022-03-28 05:58:37 +00:00
Renovate Bot
f9ba0750d6 fix(deps): update dependency webtorrent to v1.8.11 2022-03-28 00:47:47 +00:00
Renovate Bot
d98299268f fix(deps): update dependency webtorrent to v1.8.9 2022-03-27 00:08:53 +00:00
Renovate Bot
601d01fe85 fix(deps): update dependency parse-torrent to v9.1.5 2022-03-26 19:32:10 +00:00
Renovate Bot
b24cc29523 chore(deps): update dependency electron-notarize to v1.2.1 2022-03-25 10:03:02 +00:00
Renovate Bot
dd06ac7cc5 fix(deps): update dependency webtorrent to v1.8.8 2022-03-25 04:31:32 +00:00
Renovate Bot
4097c5ee18 chore(deps): update dependency electron to v15.4.2 2022-03-24 22:26:07 +00:00
Renovate Bot
240128943c chore(deps): update dependency plist to v3.0.5 2022-03-24 17:50:55 +00:00
Renovate Bot
6d8a2a0b9e chore(deps): update dependency @babel/core to v7.17.8 2022-03-19 21:08:10 +00:00
Renovate Bot
6433da4901 fix(deps): update dependency @electron/remote to v2.0.8 2022-03-16 21:23:58 +00:00
renovate[bot]
96b27fa1cb chore(deps): update dependency gh-release to v6.0.3 (#2165)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-16 12:21:09 -05:00
Renovate Bot
9134620fe7 chore(deps): update dependency @babel/core to v7.17.7 2022-03-15 19:13:56 +00:00
Renovate Bot
1ff1c035b7 fix(deps): update webtorrent 2022-03-11 16:29:50 +00:00
Renovate Bot
58e165eb30 fix(deps): update dependency @electron/remote to v2.0.7 2022-03-11 16:22:58 +00:00
Renovate Bot
4fdafc91c1 chore(deps): update dependency electron to v15.4.1 2022-03-11 16:14:31 +00:00
Renovate Bot
7ef740ebe0 fix(deps): update dependency webtorrent to v1.8.5 2022-03-06 13:25:50 +00:00
renovate[bot]
138ece60fd chore(deps): update actions/upload-artifact action to v3 (#2158)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-04 17:49:01 +01:00
renovate[bot]
a2d0cc09eb chore(deps): update actions/stale action to v5 (#2155)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Alex <alxmorais8@msn.com>
2022-03-03 15:22:31 +01:00
renovate[bot]
a701d44d25 chore(deps): update dependency hosted-git-info to 2.8.9 [security] (#2138)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Alex <alxmorais8@msn.com>
2022-03-03 15:12:18 +01:00
renovate[bot]
4a67d1c679 chore(deps): update actions/setup-node action to v3 (#2154)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-03 15:00:35 +01:00
Renovate Bot
450ecedad4 fix(deps): update dependency webtorrent to v1.8.4 2022-03-03 12:28:01 +00:00
renovate[bot]
55ea243862 chore(deps): update dependency electron to v15.4.0 (#2150)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Alex <alxmorais8@msn.com>
2022-03-03 12:42:00 +01:00
renovate[bot]
319a27399e chore(deps): update dependency tape to v5.5.2 (#2147)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Alex <alxmorais8@msn.com>
2022-03-03 12:40:30 +01:00
renovate[bot]
f532d15222 chore(deps): update actions/checkout action to v3 (#2152)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-03 12:37:01 +01:00
renovate[bot]
3b4a2da2be fix(deps): update dependency music-metadata to v7.12.2 (#2151)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-03 12:31:12 +01:00
renovate[bot]
c464074c92 fix(deps): update dependency webtorrent to v1.8.3 (#2149)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Alex <alxmorais8@msn.com>
2022-03-03 12:09:43 +01:00
renovate[bot]
4945ba9073 fix(deps): update dependency @electron/remote to v2.0.5 (#2148)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-03 12:07:52 +01:00
renovate[bot]
a4b7cfea3f chore(deps): update babel monorepo (#2146)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Alex <alxmorais8@msn.com>
2022-03-03 10:40:33 +01:00
renovate[bot]
d0ed20f10b fix(deps): update dependency chokidar to v3.5.3 (#2121)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Alex <alxmorais8@msn.com>
2022-03-03 10:36:42 +01:00
renovate[bot]
8964d9f349 fix(deps): update dependency iso-639-1 to v2.1.13 (#2081)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Alex <alxmorais8@msn.com>
2022-03-03 10:34:57 +01:00
renovate[bot]
e1525a64fc chore(deps): update dependency open to v8.4.0 (#2076)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Alex <alxmorais8@msn.com>
2022-03-03 10:29:09 +01:00
Christopher Toth
3a0415578a fix(accessibility): Fix roles and add correct label for navigation controls (#2143)
* Accessibility: Fix roles and add correct label for navigation controls

This makes screen readers properly indicate the control name, type, and state for the Back, Forward, and Add buttons.

* Update src/renderer/components/header.js

Co-authored-by: Alex <alxmorais8@msn.com>
2022-03-03 10:25:54 +01:00
dependabot[bot]
3dc023828d build(deps): bump nanoid from 3.1.23 to 3.3.1 (#2144)
Bumps [nanoid](https://github.com/ai/nanoid) from 3.1.23 to 3.3.1.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.1.23...3.3.1)

---
updated-dependencies:
- dependency-name: nanoid
  dependency-type: indirect
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-03 03:23:01 +01:00
dependabot[bot]
3d01225b6d build(deps): bump shelljs from 0.8.4 to 0.8.5 (#2145)
Bumps [shelljs](https://github.com/shelljs/shelljs) from 0.8.4 to 0.8.5.
- [Release notes](https://github.com/shelljs/shelljs/releases)
- [Changelog](https://github.com/shelljs/shelljs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/shelljs/shelljs/compare/v0.8.4...v0.8.5)

---
updated-dependencies:
- dependency-name: shelljs
  dependency-type: indirect
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-03 03:13:08 +01:00
renovate[bot]
0feb97275c fix(deps): update dependency prop-types to v15.8.1 (#2104)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Alex <alxmorais8@msn.com>
2022-03-03 03:01:40 +01:00
Alex Vale
036ac72e3c fix: remove erroneous playbackRate check (#2106)
* remove erroneous playbackRate check

A playback rate != 1 causes shouldHidePlayerControls to erroneously return false.

* Add change

Co-authored-by: Alex <alxmorais8@msn.com>
2022-03-03 01:53:23 +00:00
Renovate Bot
f097a1ed52 fix(deps): update dependency webtorrent to v1.8.1 2022-02-09 17:28:55 +00:00
Renovate Bot
16485f29c8 chore(deps): update dependency @babel/core to v7.17.2 2022-02-09 17:13:30 +00:00
Renovate Bot
0b2cb410bd fix(deps): update dependency music-metadata to v7.11.8 2022-02-04 01:29:14 +00:00
Renovate Bot
330b4adb0e chore(deps): update babel monorepo to v7.17.0 2022-02-04 01:17:08 +00:00
Renovate Bot
32818c60a4 chore(deps): update dependency electron to v15.3.6 2022-01-28 20:51:14 +00:00
Renovate Bot
a55d7e897d fix(deps): update dependency @electron/remote to v2.0.4 2022-01-28 18:52:06 +00:00
Renovate Bot
bd34106a31 fix(deps): update dependency webtorrent to v1.7.2 2022-01-28 00:31:23 +00:00
Renovate Bot
85fb83fb67 chore(deps): update dependency tape to v5.5.0 2022-01-27 21:03:52 +00:00
renovate[bot]
0cfce0ff26 fix(deps): update dependency simple-get to v4.0.1 (#2124) 2022-01-24 23:03:59 -05:00
Renovate Bot
65147eb53a chore(deps): update dependency @babel/core to v7.16.12 2022-01-23 16:22:43 +00:00
Renovate Bot
5b6d29efcb fix(deps): update dependency webtorrent to v1.7.1 2022-01-20 18:45:36 +00:00
Renovate Bot
c5c53646eb fix(deps): update dependency music-metadata to v7.11.7 2022-01-18 15:06:57 +00:00
Renovate Bot
0927cedfa0 fix(deps): update dependency webtorrent to v1.6.0 2022-01-18 00:41:33 +00:00
Renovate Bot
22962e9b7c chore(deps): update dependency tape to v5.4.1 2022-01-17 05:31:02 +00:00
Renovate Bot
13932b0567 fix(deps): update dependency music-metadata to v7.11.6 2022-01-14 09:42:12 +00:00
Renovate Bot
ed38a55711 fix(deps): update dependency webtorrent to v1.5.11 2022-01-14 03:46:52 +00:00
Renovate Bot
e55d9b6d15 chore(deps): update dependency electron to v15.3.5 2022-01-13 03:57:35 +00:00
Renovate Bot
e15ae42c32 fix(deps): update dependency webtorrent to v1.5.9 2022-01-12 19:09:47 +00:00
Renovate Bot
a71808445e chore(deps): update dependency @babel/cli to v7.16.8 2022-01-11 23:30:20 +00:00
Renovate Bot
b742b10553 chore(deps): update dependency depcheck to v1.4.3 2022-01-10 20:32:22 +00:00
Renovate Bot
e8e9314486 chore(deps): update babel monorepo to v7.16.7 2022-01-01 02:06:53 +00:00
Renovate Bot
0b16be24c1 chore(deps): update dependency tape to v5.4.0 2021-12-27 08:13:46 +00:00
Renovate Bot
a90df37123 chore(deps): update dependency electron to v15.3.4 2021-12-17 21:37:54 +00:00
Renovate Bot
fc7608fa87 chore(deps): update babel monorepo to v7.16.5 2021-12-15 00:20:04 +00:00
Renovate Bot
82a61e9da4 chore(deps): update dependency electron to v15.3.3 2021-12-02 00:33:53 +00:00
Renovate Bot
2d0c1d597f chore(deps): update dependency tape to v5.3.2 2021-11-17 08:31:43 +00:00
Renovate Bot
4a9566665e chore(deps): update dependency electron to v15.3.2 2021-11-17 02:41:06 +00:00
Renovate Bot
fad7a21287 chore(deps): update dependency @babel/eslint-parser to v7.16.3 2021-11-10 21:58:46 +00:00
Renovate Bot
7893da9426 chore(deps): update dependency nodemon to v2.0.15 2021-11-10 19:46:09 +00:00
Renovate Bot
f0ddc79fcc chore(deps): update dependency electron to v15.3.1 2021-11-09 19:56:29 +00:00
Renovate Bot
f92afd3f10 chore(deps): update babel monorepo to v7.16.0 2021-10-31 00:31:49 +00:00
Renovate Bot
9ce6c3b461 chore(deps): update dependency electron-osx-sign to v0.6.0 2021-10-30 00:38:05 +00:00
Renovate Bot
b404b44aa1 fix(deps): update dependency webtorrent to v1.5.8 2021-10-26 19:12:55 +00:00
Renovate Bot
8c38377e38 fix(deps): update dependency webtorrent to v1.5.7 2021-10-25 19:02:31 +00:00
Renovate Bot
eda83e858d chore(deps): update dependency electron to v15.3.0 2021-10-21 18:02:23 +00:00
Renovate Bot
a6639aadcf chore(deps): update dependency nodemon to v2.0.14 2021-10-20 14:33:30 +00:00
Renovate Bot
2cc62e26b3 chore(deps): update dependency electron to v15.2.0 2021-10-15 22:43:17 +00:00
Diego Rodríguez Baquero
e42a515199 fix: modernify code (#2068)
* fix: modernify code

* standard fix

* fixes
2021-10-11 18:23:09 -05:00
Diego Rodríguez Baquero
c36e43eaa3 fix: electron upgrade fixes (#2058)
* fix: electron upgrade fixes

* fix: electron remote

* fixes

* fixes

* pin

* actually
2021-10-10 13:21:45 -05:00
Renovate Bot
0732bd93d2 chore(deps): update dependency electron to v15.1.2 2021-10-09 19:34:19 +00:00
Renovate Bot
f12027f836 chore(deps): update babel monorepo to v7.15.8 2021-10-07 21:33:39 +00:00
Renovate Bot
d4dfaa6047 chore(deps): update dependency electron to v15.1.1 2021-10-05 23:46:19 +00:00
Renovate Bot
809d122d98 fix(deps): update dependency webtorrent to v1.5.6 2021-10-05 17:07:29 +00:00
Renovate Bot
6dbbf8b85b fix(deps): update dependency chromecasts to v1.10.2 2021-10-05 15:11:48 +00:00
Renovate Bot
3150c04ef4 chore(deps): update dependency electron to v15.1.0 2021-10-02 16:55:35 +00:00
Alex
770c641f1b refactor: ETA calculation (#2055)
* Refactor ETA calculation

* Update src/renderer/pages/player-page.js

Co-authored-by: Alex <alxmorais8@msn.com>

* Fix lint issue

Co-authored-by: Alex <alxmorais8@msn.com>
2021-10-02 15:11:45 +02:00
Renovate Bot
9c0ad29db9 chore(deps): update dependency nodemon to v2.0.13 2021-09-24 21:10:00 +00:00
renovate[bot]
add6b2e900 chore(deps): update dependency electron to v15 (#2051)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-23 10:41:07 -05:00
Renovate Bot
83c2e7d731 fix(deps): update dependency music-metadata to v7.11.4 2021-09-23 03:38:47 +00:00
Renovate Bot
29393b1803 chore(deps): update dependency electron-packager to v15.4.0 2021-09-23 03:33:12 +00:00
Renovate Bot
0ba4d3b831 chore(deps): update dependency electron-notarize to v1.1.1 2021-09-23 03:26:29 +00:00
Renovate Bot
872f60e161 chore(deps): update babel monorepo 2021-09-23 03:17:49 +00:00
Renovate Bot
65886933ee fix(deps): update dependency chromecasts to v1.10.1 2021-09-23 03:07:39 +00:00
Renovate Bot
f300d8af21 chore(deps): update dependency plist to v3.0.4 2021-09-23 02:57:06 +00:00
Renovate Bot
f87068a288 chore(deps): update dependency gh-release to v6.0.1 2021-09-23 02:45:16 +00:00
renovate[bot]
1916f4f1a3 chore(deps): update dependency electron to v13.4.0 (#1997)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-22 20:53:54 -05:00
renovate[bot]
b0d9b89451 chore(deps): update actions/setup-node action to v2 (#2052)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-09-22 20:51:12 -05:00
Benjamin Tan
0d512db6e2 Ensure that default file/protocol handlers are re-installed after updating. (#997)
Previously, they were only installed when the preference was changed.
This caused the handlers to point to non-existing files after updates
occurred and older versions were removed by Squirrel.

Closes #791, #911.
2021-09-22 20:11:53 -05:00
Vincenzo De Petris
24969c87f3 Fix ghost image showing on media player drag (#1922)
* fix: ghost image showing on media player drag

* fix: add missing space

* fix: access Image from window object
2021-09-22 20:10:30 -05:00
Adam Gotlib
5619f1805b Release media keys when opening external player (#1237) 2021-09-22 20:07:00 -05:00
Alex
e9d72ebb17 fix: resume torrents after deletion (#1974)
* fix: resume torrents after deletion

* Update torrent-list-controller.js

Co-authored-by: Diego Rodríguez Baquero <github@diegorbaquero.com>
2021-09-22 19:56:00 -05:00
Julen Garcia Leunda
c7647440ba build: add package Github Action (#1888)
* Add package Github Action

* Update package.yml

Co-authored-by: Diego Rodríguez Baquero <github@diegorbaquero.com>
2021-09-22 19:52:06 -05:00
Renovate Bot
86ba117e04 fix(deps): update dependency webtorrent to v1.5.5 2021-09-02 13:01:29 +00:00
Renovate Bot
27cf60d5dc fix(deps): update dependency webtorrent to v1.5.4 2021-08-25 23:15:05 +00:00
Renovate Bot
d06cddd94a fix(deps): update dependency webtorrent to v1.5.3 2021-08-20 19:17:40 +00:00
Renovate Bot
21ad84daf8 fix(deps): update dependency webtorrent to v1.5.1 2021-08-20 02:28:03 +00:00
Renovate Bot
c882e13889 fix(deps): update dependency webtorrent to v1.4.0 2021-08-17 20:38:57 +00:00
Renovate Bot
9a68910e31 fix(deps): update dependency webtorrent to v1.3.10 2021-08-16 14:21:14 +00:00
Agyant Tiwari
610abea1c3 Play/Pause video on click (#1878)
* Play/Pause video on click

* Fixing lint

* fix: use dispatcher

Co-authored-by: Alex <alxmorais8@msn.com>
2021-08-16 13:47:53 +02:00
Renovate Bot
b132fb73df chore(deps): update dependency tape to v5.3.1 2021-08-08 07:07:12 +00:00
Renovate Bot
eff52911c2 fix(deps): update dependency webtorrent to v1.3.9 2021-08-07 00:35:35 +00:00
Renovate Bot
3ff41a965f fix(deps): update dependency create-torrent to v5.0.1 2021-08-06 22:42:34 +00:00
Renovate Bot
8373fd17b8 fix(deps): update dependency webtorrent to v1.3.8 2021-08-06 05:07:39 +00:00
renovate[bot]
c531169a37 fix(deps): update dependency create-torrent to v5 (#2034)
* fix(deps): update dependency create-torrent to v5

* Update webtorrent.js

Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Diego Rodríguez Baquero <github@diegorbaquero.com>
2021-08-05 20:54:37 -05:00
renovate[bot]
d00b9ba081 fix(deps): update dependency webtorrent to v1.3.7 (#2033)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-05 07:49:04 +00:00
renovate[bot]
1d644c82de fix(deps): update webtorrent (#2032)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-05 02:22:15 +00:00
renovate[bot]
d6308734ea fix(deps): update dependency chromecasts to v1.10.0 (#1991)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-04 15:09:59 -05:00
renovate[bot]
534c6719d1 chore(deps): update dependency electron-notarize to v1.0.1 (#2027)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-03 19:25:10 -05:00
renovate[bot]
4e4315160e fix(deps): update dependency chokidar to v3.5.2 (#1993)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-03 19:23:40 -05:00
renovate[bot]
25398030fa chore(deps): update babel monorepo (#1992)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-03 19:22:50 -05:00
renovate[bot]
b261a24bda chore(deps): update dependency open to v8.2.1 (#1996)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-03 19:21:56 -05:00
renovate[bot]
dcbe5851c2 fix(deps): update dependency drag-drop to v7.2.0 (#2004)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-03 19:21:28 -05:00
renovate[bot]
24ef81387e chore(deps): update dependency tape to v5.3.0 (#2023)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-03 19:16:45 -05:00
renovate[bot]
6a761c9a10 chore(deps): update dependency electron-packager to v15.3.0 (#2016)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-08-03 19:16:33 -05:00
Renovate Bot
8ac6e9effe chore(deps): update dependency nodemon to v2.0.12 2021-08-03 23:51:42 +00:00
Renovate Bot
fec063bd1d fix(deps): update dependency webtorrent to v1.3.4 2021-07-30 17:56:47 +00:00
Renovate Bot
8b76535ce2 fix(deps): update dependency webtorrent to v1.3.3 2021-07-25 02:21:47 +00:00
Renovate Bot
7072caf3ce fix(deps): update dependency webtorrent to v1.3.2 2021-07-24 20:29:48 +00:00
Renovate Bot
2ba8fd20ee fix(deps): update dependency webtorrent to v1.3.0 2021-07-24 00:22:23 +00:00
Renovate Bot
7f962109e9 fix(deps): update dependency webtorrent to v1.2.6 2021-07-23 20:45:48 +00:00
Renovate Bot
33e6b6565c fix(deps): update dependency create-torrent to v4.7.1 2021-07-22 16:38:52 +00:00
Diego Rodríguez Baquero
04cdc64a18 chore: add stale 2021-07-21 19:20:42 -05:00
Renovate Bot
452bc0e235 fix(deps): update dependency webtorrent to v1.2.5 2021-07-19 17:26:26 +00:00
Renovate Bot
607c5b8c11 fix(deps): update dependency webtorrent to v1.2.4 2021-07-13 22:53:36 +00:00
Renovate Bot
7ef697ed72 fix(deps): update dependency webtorrent to v1.2.3 2021-07-13 20:32:00 +00:00
Renovate Bot
86182417cc fix(deps): update dependency webtorrent to v1.2.2 2021-07-11 04:09:25 +00:00
Renovate Bot
200f385d23 fix(deps): update dependency webtorrent to v1.2.0 2021-07-10 00:09:01 +00:00
Renovate Bot
8a5140d93d fix(deps): update dependency webtorrent to v1.1.6 2021-07-08 22:26:41 +00:00
Renovate Bot
a5c2fa08a5 fix(deps): update dependency webtorrent to v1.1.5 2021-07-06 18:43:20 +00:00
Renovate Bot
d0198a4419 fix(deps): update dependency webtorrent to v1.1.4 2021-07-03 06:48:43 +00:00
Renovate Bot
de1b38e660 fix(deps): update dependency webtorrent to v1.1.3 2021-07-03 00:49:17 +00:00
Renovate Bot
50bf04c73a fix(deps): update dependency webtorrent to v1.1.0 2021-06-30 22:08:43 +00:00
Renovate Bot
1cfa101b90 fix(deps): update dependency webtorrent to v1.0.4 2021-06-30 07:13:21 +00:00
Renovate Bot
14e2775980 fix(deps): update dependency webtorrent to v1.0.2 2021-06-23 20:32:19 +00:00
Julen Garcia Leunda
8e86c855d3 Add armv7l arch support (#1901) 2021-06-12 12:50:48 -05:00
renovate[bot]
01b3772138 fix(deps): update dependency music-metadata to v7.8.6 (#1958)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-12 12:50:16 -05:00
renovate[bot]
1f84a81d97 chore(deps): update dependency electron to v13.1.0 (#1983)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-12 12:49:19 -05:00
renovate[bot]
12ab547bbc chore(deps): update babel monorepo to v7.14.5 (#1990)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-12 12:49:02 -05:00
Alex
ef4fc2d28d feat: paste torrent address with right click (#1989)
* feat: paste torrent address with right click

* Change right click to directly pasting
2021-06-09 23:55:40 +02:00
Feross Aboukhadijeh
d12fd7768a fix: Link to VLC using HTTPS (#1987)
May help with users who are man-in-the-middled and redirected to malicious websites.

See: https://github.com/webtorrent/webtorrent-desktop/issues/1908
2021-06-02 16:46:17 -07:00
Feross Aboukhadijeh
756480a69f chore: Update to Electron 13; Bump all deps (#1986)
* chore: Update to Electron 12; Bump all deps

* Fixes for Electron 12

* chore: Update to Electron 13
2021-06-02 08:21:35 -07:00
renovate[bot]
19a8e9aa3e chore(deps): update dependency gh-release to v6 (#1961)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Feross Aboukhadijeh <feross@feross.org>
2021-06-02 08:04:27 -07:00
renovate[bot]
23f20546f7 chore(deps): pin dependency electron to v11.1.0 (#1976)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-02 08:00:12 -07:00
renovate[bot]
7a2d1d1807 fix(deps): update dependency webtorrent to v0.118.0 (#1981)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-02 07:59:43 -07:00
renovate[bot]
0138a178c3 fix(deps): update dependency iso-639-1 to v2.1.9 (#1948)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-02 07:56:22 -07:00
renovate[bot]
ff6900d8f1 fix(deps): update dependency semver to v7.3.5 (#1949)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-02 07:54:49 -07:00
renovate[bot]
7217d45ff9 fix(deps): update react monorepo to v17.0.2 (#1950)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-02 07:53:00 -07:00
renovate[bot]
ba86131e4a chore(deps): update dependency electron-winstaller to v5 (#1960)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-02 07:52:21 -07:00
renovate[bot]
b57278f7f1 chore(deps): update dependency open to v8 (#1962)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-02 07:52:03 -07:00
renovate[bot]
c9136422b9 fix(deps): update dependency drag-drop to v7 (#1964)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-02 07:51:57 -07:00
renovate[bot]
34692dfd38 chore(deps): update babel monorepo (#1951)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-02 07:51:49 -07:00
renovate[bot]
a990b00b21 chore(deps): update dependency ws to 7.4.6 [security] (#1972)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-02 07:41:44 -07:00
Alberto Miranda
5f5e4e0ee2 Fix cannot set property 'enabled' of undefined (#1938) 2021-06-02 07:41:09 -07:00
Feross Aboukhadijeh
e9fa721ca8 Switch from Travis to GitHub Actions (#1978) 2021-06-02 07:33:48 -07:00
Feross Aboukhadijeh
7ba1510131 chore: Set node 16 and npm 7 as minimum versions (#1977) 2021-06-02 07:25:48 -07:00
renovate[bot]
057c192dc4 chore(deps): update dependency electron to 11.1.0 [security] (#1939)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-06-02 07:18:43 -07:00
renovate[bot]
b78966ae2e chore(deps): pin dependencies (#1965)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-31 22:02:24 -05:00
renovate[bot]
2c34f7af1c chore(deps): update dependency lodash to 4.17.21 [security] (#1941)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-24 08:09:49 -05:00
renovate[bot]
6885d23bde fix(deps): update dependency debounce to ^1.2.1 (#1947)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2021-05-24 08:09:16 -05:00
Diego Rodríguez Baquero
277010a1b8 Merge pull request #1956 from webtorrent/renovate_tape-5.x
chore(deps): update dependency tape to ^5.2.2
2021-05-24 08:08:00 -05:00
Diego Rodríguez Baquero
d0849accbb Merge pull request #1957 from webtorrent/renovate_chokidar-3.x
fix(deps): update dependency chokidar to ^3.5.1
2021-05-24 08:06:23 -05:00
Renovate Bot
080e8da591 fix(deps): update dependency chokidar to ^3.5.1 2021-05-24 04:34:36 +00:00
Renovate Bot
bf0b5f8cdb chore(deps): update dependency tape to ^5.2.2 2021-05-24 04:33:03 +00:00
Diego Rodríguez Baquero
6e151cd2a1 chore: add renovate config 2021-05-23 23:00:09 -05:00
Alex
62273fa6b2 Merge pull request #1932 from webtorrent/dependabot/npm_and_yarn/ua-parser-js-0.7.28
Bump ua-parser-js from 0.7.22 to 0.7.28
2021-05-07 11:31:34 +02:00
dependabot[bot]
00d0c3d828 Bump ua-parser-js from 0.7.22 to 0.7.28
Bumps [ua-parser-js](https://github.com/faisalman/ua-parser-js) from 0.7.22 to 0.7.28.
- [Release notes](https://github.com/faisalman/ua-parser-js/releases)
- [Commits](https://github.com/faisalman/ua-parser-js/compare/0.7.22...0.7.28)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-06 21:11:35 +00:00
Feross Aboukhadijeh
61efbd6823 Merge pull request #1928 from RayBB/patch-1
update brew install command
2021-04-26 16:17:48 -07:00
Alex
e6a33fb53a Merge pull request #1905 from getsnoopy/fix-units
Fix formatting of measurement units
2021-04-14 09:57:26 +02:00
Alex
228d733539 Merge pull request #1927 from webtorrent/dependabot/npm_and_yarn/y18n-4.0.1
Bump y18n from 4.0.0 to 4.0.1
2021-04-14 09:53:16 +02:00
Raymond Berger
83eb584422 update brew install command 2021-04-10 19:24:07 -10:00
dependabot[bot]
47e89813a0 Bump y18n from 4.0.0 to 4.0.1
Bumps [y18n](https://github.com/yargs/y18n) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/yargs/y18n/releases)
- [Changelog](https://github.com/yargs/y18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yargs/y18n/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-30 09:23:23 +00:00
Alex
f0894ced54 Merge pull request #1904 from webtorrent/dependabot/npm_and_yarn/ini-1.3.7
Bump ini from 1.3.5 to 1.3.7
2021-02-01 18:37:45 +01:00
Alex
5372887d46 Merge pull request #1920 from BlueManCZ/tray-fix
Improve libappindicator checking
2021-02-01 18:37:13 +01:00
BlueManCZ
f8d9567422 Change command 2021-01-31 22:21:13 +01:00
BlueManCZ
97b54744df Update comment 2021-01-31 11:19:44 +01:00
BlueManCZ
4a974a1d3d Look for libappindicator libraries instead of package 2021-01-31 11:12:18 +01:00
BlueManCZ
192560755c Merge branch 'master' of github.com:webtorrent/webtorrent-desktop 2021-01-31 10:40:05 +01:00
Varun Varada
d299704f57 Fix formatting of measurement units
There were some incorrectly formatted unit symbols and units names in
the app, so this commit fixes them per SI and ISO/IEC specifications.
2020-12-22 19:00:05 -06:00
dependabot[bot]
314e74d1ed Bump ini from 1.3.5 to 1.3.7
Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.7.
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.7)

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-10 23:07:23 +00:00
Feross Aboukhadijeh
919af5bf15 Merge pull request #1217 from cezar-carneiro/show-progress-on-cast-screen 2020-11-26 01:44:32 +01:00
Feross Aboukhadijeh
d819acedd5 Merge pull request #1865 from BlueManCZ/patch-1 2020-11-25 22:33:25 +01:00
Feross Aboukhadijeh
54fcc5057b recursively update all deps 2020-11-24 12:02:08 -10:00
Feross Aboukhadijeh
cd5da2fe9b cross-zip@4 2020-11-24 12:00:00 -10:00
Feross Aboukhadijeh
1c79ffc720 bump deps; including electron ~11.0.3
Fixes: https://github.com/webtorrent/webtorrent-desktop/issues/1896
2020-11-24 11:56:17 -10:00
Feross Aboukhadijeh
a1a590fbba travis: disable cache
the cache keeps caching outdated versions which cause test failures
2020-11-22 16:32:36 -10:00
Feross Aboukhadijeh
606c02aef4 Remove extra-lint
- standard enforces 'let' and 'const' now
- I've never been a fan of the <100 chars per line rule since it violates the standard philosophy. it should be possible to write conformant code without needing a tool, so 'magic numbers' like 'no more than X lines/chars/statements' are not ideal
2020-11-22 16:29:59 -10:00
Feross Aboukhadijeh
4f68a8ad0b parse-torrent@9 2020-11-22 16:26:42 -10:00
Feross Aboukhadijeh
37d962fcf3 bump deps 2020-11-22 16:24:46 -10:00
Feross Aboukhadijeh
baf06461df Remove unused 'buble' dependency 2020-11-22 16:20:09 -10:00
Feross Aboukhadijeh
464e63fd92 standard (Fixes for PR #1818) 2020-11-22 16:12:04 -10:00
Feross Aboukhadijeh
2761e9c768 Merge pull request #1818 from surajrathod/master 2020-11-23 03:11:34 +01:00
suraj rathod
0efb5fa7ad Merge branch 'master' into master 2020-11-20 11:27:33 +05:30
Feross Aboukhadijeh
34947c355d standard@16 2020-11-18 12:38:20 -10:00
Feross Aboukhadijeh
958814f2ea use @babel/eslint-parser 2020-11-18 12:37:03 -10:00
Feross Aboukhadijeh
ec0c0c7870 Update package-lock.json 2020-11-18 12:30:13 -10:00
Feross Aboukhadijeh
ec0a1d1bb4 Merge pull request #1895 from webtorrent/electron11 2020-11-18 03:41:45 +01:00
Feross Aboukhadijeh
969d71afec Merge pull request #1698 from webtorrent/babel
Use babel instead of buble
2020-11-18 03:41:19 +01:00
Feross Aboukhadijeh
c1db01b936 Use babel instead of buble
This way we can target just the JSX tranformation. We don't use any other cutting edge JS features that require compilation, nor should we in the future.
2020-11-17 16:40:14 -10:00
Feross Aboukhadijeh
90670a4645 changelog: add link to security issue explanation 2020-11-17 15:42:11 -10:00
Feross Aboukhadijeh
b5fad54f4a Upgrade to Electron 11 2020-11-16 18:03:35 -10:00
Feross Aboukhadijeh
50718d3791 Merge pull request #1887 from webtorrent/fix_lintian_warnings
Fix lintian warnings
2020-11-09 22:58:14 +01:00
Julen Garcia Leunda
bd54a8c214 Fix lintian warnings 2020-11-06 17:13:22 +01:00
Feross Aboukhadijeh
0cd0edf4cc Merge pull request #1886 from webtorrent/throttling
Disable background throttling
2020-11-05 22:30:22 +01:00
Feross Aboukhadijeh
9e0d91f144 Disable background throttling
Reference: https://github.com/webtorrent/webtorrent-desktop/pull/1720#issuecomment-722011487

I actually think we want backgroundThrottling: false so our timers and intervals aren't throttled when the app is backgrounded.
2020-11-04 12:34:48 -10:00
Feross Aboukhadijeh
38d9c4c504 Merge pull request #1885 from webtorrent/bitfield
bitfield@4
2020-11-04 10:15:40 +01:00
Feross Aboukhadijeh
9e1721990d bitfield@4 2020-11-03 13:03:40 -10:00
Feross Aboukhadijeh
a20f82cc61 standard 2020-10-29 11:30:07 -10:00
Feross Aboukhadijeh
630ed76b8c standard 2020-10-28 09:52:07 -10:00
Feross Aboukhadijeh
1155cba4dd Merge pull request #1883 from webtorrent/deps 2020-10-28 19:18:16 +01:00
Feross Aboukhadijeh
2343181e1b Update package-lock.json 2020-10-28 08:15:53 -10:00
Feross Aboukhadijeh
9bb7330caa spectron@12 2020-10-28 08:14:10 -10:00
Feross Aboukhadijeh
3aae1614ea pngjs@6 2020-10-28 08:13:13 -10:00
Feross Aboukhadijeh
cdd308fc4a gh-release@4 2020-10-28 08:12:11 -10:00
Feross Aboukhadijeh
594d18e76e react 17 2020-10-28 08:11:10 -10:00
Feross Aboukhadijeh
50d772eb54 parse-torrent@8 2020-10-28 08:10:43 -10:00
Feross Aboukhadijeh
57ffb5e0c4 bump deps 2020-10-28 08:10:26 -10:00
Feross Aboukhadijeh
49ab4bd201 Merge pull request #1882 from webtorrent/render-deprecated 2020-10-28 19:07:03 +01:00
Feross Aboukhadijeh
7b06acb972 don't rely on deprecated return value from ReactDOM.render 2020-10-27 18:18:30 -10:00
Feross Aboukhadijeh
80b86b5693 standard 2020-10-21 13:50:42 -10:00
Diego Rodríguez Baquero
748b996522 Merge pull request #1875 from webtorrent/dependabot/npm_and_yarn/electron-10.1.2
Bump electron from 10.1.1 to 10.1.2
2020-10-20 10:51:26 -05:00
Julen Garcia Leunda
77877d4201 Merge pull request #1812 from dsernst/scrub-preview
Adds Youtube-style Scrubbing preview
2020-10-20 17:31:43 +02:00
dependabot[bot]
696fa4479c Bump electron from 10.1.1 to 10.1.2
Bumps [electron](https://github.com/electron/electron) from 10.1.1 to 10.1.2.
- [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/v10.1.1...v10.1.2)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-06 17:49:29 +00:00
Feross Aboukhadijeh
e0bb7562be Update package-lock.json 2020-09-03 11:36:21 -07:00
Feross Aboukhadijeh
8f20d9676b electron 10.1.1 2020-09-03 11:35:08 -07:00
BlueManCZ
b61a4e84f5 Remove Version entry 2020-08-29 14:19:36 +02:00
BlueManCZ
9c59157a98 Remove VERSION entry 2020-08-29 14:03:27 +02:00
Ivo Šmerek
5def2d3947 Fix StartupWMClass 2020-08-29 13:53:02 +02:00
Feross Aboukhadijeh
ce6326a869 Update RELEASE_PROCESS.md 2020-08-28 17:58:07 -07:00
Feross Aboukhadijeh
7e56550887 Update RELEASE_PROCESS.md 2020-08-28 17:51:12 -07:00
Feross Aboukhadijeh
aa42627d45 0.24.0 2020-08-28 17:19:47 -07:00
Feross Aboukhadijeh
bd6dc1a7c1 authors 2020-08-28 17:19:20 -07:00
Feross Aboukhadijeh
dfedbcea32 add 0.24.0 changelog 2020-08-28 17:18:42 -07:00
Feross Aboukhadijeh
d930b97b30 Merge pull request #1864 from webtorrent/update 2020-08-28 17:14:58 -07:00
Feross Aboukhadijeh
de7899c8f8 Update package-lock.json 2020-08-28 17:06:51 -07:00
Feross Aboukhadijeh
2f53c5e137 bump electron deps 2020-08-28 17:03:33 -07:00
Feross Aboukhadijeh
ff54f48abb bump deps 2020-08-28 17:00:29 -07:00
Feross Aboukhadijeh
a7766e8d3f fixes for capture-frame@4 2020-08-28 16:58:40 -07:00
Feross Aboukhadijeh
844e34e596 capture-frame@4 2020-08-28 16:58:36 -07:00
Julen Garcia Leunda
8515fee681 Merge pull request #1859 from webtorrent/add_m2ts_video_container
Add m2ts video container support
2020-08-17 21:58:32 +02:00
Borewit
10a1ee3a09 Merge pull request #1861 from webtorrent/update-music-metadata
Update music-metadata to version 7.0.2
2020-08-17 19:26:32 +02:00
Borewit
a1b2641130 Update music-metadata to version 7.0.2 2020-08-16 08:48:37 +02:00
Julen Garcia Leunda
bb55b3fab2 Add m2ts video container support 2020-08-12 23:06:14 +02:00
Julen Garcia Leunda
57d02aa316 Merge pull request #1850 from Hinara/patch-1
Fix #1807 (VLC does not start)
2020-07-31 17:11:07 +02:00
David Ernst
d3bfccaa6b Check for type === video in clearPreview() 2020-07-30 19:10:14 -07:00
Julen Garcia Leunda
3a92f596ff Merge pull request #1838 from webtorrent/update-trackers
Update trackers to be consistent
2020-07-30 18:31:43 +02:00
Julen Garcia Leunda
60b4365a76 Merge pull request #1840 from subins2000/fix-1839-no-keyevents-on-user-input
Fix #1839: Prevent keypress events on user input elements
2020-07-30 18:31:22 +02:00
Julen Garcia Leunda
cb0ad73c80 Merge pull request #1754 from hicom150/fix_windows_installer
Fix windows installer event handler
2020-07-30 18:30:59 +02:00
Julen Garcia Leunda
9c865050bb Merge pull request #1847 from webtorrent/update-music-metadata
Update music metadata
2020-07-30 18:30:08 +02:00
Hinara
0edeaa4d58 Accept null value as playerPath 2020-07-30 15:06:26 +02:00
Mathias Rasmussen
dfd1ca3a8e Merge pull request #1841 from webtorrent/update_loading_gif
Update loading GIF
2020-07-30 03:59:49 +02:00
Borewit
75d9939b98 Update dependency music-metadata to version 7 2020-07-29 18:00:29 +02:00
Hinara
f88d5426c9 Fix #1807
eb5a291c8b/src/renderer/lib/migrations.js (L219) cause external player to be a empty string instead of a null one
2020-07-25 02:39:09 +02:00
Borewit
1b7d4f09a9 Fix issue #1833, only pass metadata. Prevent MetadataCollector (from music-metadata) is serialized. 2020-07-21 23:00:22 +02:00
Alex
680376c4a6 Update loading.gif 2020-07-17 21:14:15 +02:00
Subin Siby
15cca44bd2 Fix #1839: Prevent keypress events on user input elements 2020-07-17 18:47:23 +05:30
Feross Aboukhadijeh
29d17870cb Update trackers to be consistent
Updated all .torrent files to include:

```
  "announce": [
    "udp://tracker.leechers-paradise.org:6969",
    "udp://tracker.coppersurfer.tk:6969",
    "udp://tracker.opentrackr.org:1337",
    "udp://explodie.org:6969",
    "udp://tracker.empire-js.us:1337",
    "wss://tracker.btorrent.xyz",
    "wss://tracker.openwebtorrent.com"
  ]
```

Removed dead trackers from the list.
2020-07-16 20:18:15 -07:00
Feross Aboukhadijeh
c150d22c97 Update package-lock.json 2020-07-16 10:14:43 -07:00
Feross Aboukhadijeh
4e0c1ed393 Update CHANGELOG.md 2020-07-15 23:04:06 -07:00
Feross Aboukhadijeh
c6240c3253 Update CHANGELOG.md 2020-07-15 22:38:58 -07:00
Feross Aboukhadijeh
5deb0d7e9a Merge pull request #1835 from webtorrent/osx-notarize
Add macOS Notarization
2020-07-16 07:28:56 +02:00
Feross Aboukhadijeh
803cce808b Add macOS Notarization
Fixes: https://github.com/webtorrent/webtorrent-desktop/issues/1675
2020-07-15 22:26:29 -07:00
Feross Aboukhadijeh
8e89c0962b 0.23.0 2020-07-15 20:13:51 -07:00
Feross Aboukhadijeh
50cc394a27 Update CHANGELOG.md 2020-07-15 20:13:51 -07:00
Feross Aboukhadijeh
0165d541b8 update dep 2020-07-15 20:13:51 -07:00
Feross Aboukhadijeh
5af36428fa Merge pull request #1834 from webtorrent/electron10 2020-07-16 05:01:40 +02:00
Feross Aboukhadijeh
48ad571a59 electron 10: re-enable remote module
Electron 10 disables the remote module by default. We've always tried to avoid using `remote` in WTD so there aren't many occurrances of it, but there are still a few places where we use it
2020-07-15 20:01:08 -07:00
Feross Aboukhadijeh
57a003d7c5 electron 10 crash reporter changes
Crash reporter doesn't need to be started in child processes, and in fact the functions are all deprecated. Instead start it from the main process, and the child processes will automatically be covered

Change of params to crashReporter.start() function
2020-07-15 19:44:34 -07:00
Feross Aboukhadijeh
5f5b13d7fe update to electron 10.0.0-beta.11 2020-07-15 19:42:08 -07:00
Feross Aboukhadijeh
ed3f3f11f6 update tape, pngjs deps 2020-07-15 19:24:08 -07:00
Feross Aboukhadijeh
0572997a44 Update RELEASE_PROCESS.md 2020-07-15 19:15:47 -07:00
Feross Aboukhadijeh
4ce10859e7 0.22.0 changelog formatting 2020-07-15 18:17:03 -07:00
Feross Aboukhadijeh
eb5a291c8b Update RELEASE_PROCESS.md 2020-07-15 18:02:30 -07:00
Feross Aboukhadijeh
4b6394d0d5 0.22.0 2020-07-15 17:55:28 -07:00
Feross Aboukhadijeh
6b075ebe83 update integration tests to pass 2020-07-15 17:55:02 -07:00
Feross Aboukhadijeh
9b4dea29f4 lock spectron to 11.0.0
11.1.0 contains breaking changes. See: https://github.com/electron-userland/spectron/issues/647
2020-07-15 16:38:55 -07:00
Feross Aboukhadijeh
a2539b15d5 Prep for 0.22.0 release
Supercedes: https://github.com/webtorrent/webtorrent-desktop/pull/1730

Thanks @hicom150 :)
2020-07-15 15:39:39 -07:00
Feross Aboukhadijeh
a0da514f33 Update package.js 2020-07-15 15:22:01 -07:00
Feross Aboukhadijeh
ff5ae7a054 authors 2020-07-15 14:47:28 -07:00
Feross Aboukhadijeh
27bbdcc465 fixes for Electron 9 2020-07-15 14:35:03 -07:00
Feross Aboukhadijeh
1f19ed9a2d update electron to 9; update related deps 2020-07-15 14:34:27 -07:00
Feross Aboukhadijeh
06ce97bf6c Remove mkdirp
Fixes: https://github.com/webtorrent/webtorrent-desktop/issues/1831
2020-07-15 14:03:27 -07:00
Feross Aboukhadijeh
5c67a561c1 update easy deps
Update deps

from ~70 down to 34 vulnerabilities (33 low, 1 moderate)
2020-07-15 14:03:26 -07:00
Feross Aboukhadijeh
1ee49318fc Merge pull request #1830 from webtorrent/dependabot/npm_and_yarn/lodash-4.17.19
Bump lodash from 4.17.15 to 4.17.19
2020-07-15 13:47:25 -07:00
dependabot[bot]
cc06379ce8 Bump lodash from 4.17.15 to 4.17.19
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-15 20:38:26 +00:00
Feross Aboukhadijeh
66ac79c709 Merge pull request #1828 from webtorrent/dependabot/npm_and_yarn/electron-7.2.4 2020-07-15 13:37:32 -07:00
dependabot[bot]
ad252c5fc6 Bump electron from 7.1.0 to 7.2.4
Bumps [electron](https://github.com/electron/electron) from 7.1.0 to 7.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/v7.1.0...v7.2.4)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-07 00:30:18 +00:00
SurajRathod
ab9f86d6c9 added .vscode ignore 2020-06-06 17:47:38 +05:30
SurajRathod
583cecc661 selective import 2020-06-06 17:46:30 +05:30
Feross Aboukhadijeh
3d66d32597 Merge pull request #1806 from LinusU/object-shorthand 2020-05-17 12:43:29 -07:00
Feross Aboukhadijeh
e4962fca52 Merge pull request #1776 from webtorrent/greenkeeper/cross-zip-3.0.0 2020-05-10 11:34:04 -07:00
David Ernst
c4b318bd5f Clean up code and add better comments 2020-05-02 11:40:00 -07:00
David Ernst
d55acf9c12 Fix 'extra-lint' errors 2020-05-01 22:41:19 -07:00
David Ernst
24bc40c95e Fix preview border rendering 2020-05-01 22:06:05 -07:00
David Ernst
0716444be5 Working video scrubbing preview 2020-05-01 21:57:42 -07:00
David Ernst
85c0e99e16 Only show previews for video 2020-05-01 21:05:29 -07:00
David Ernst
0b57961ff7 Basic placeholder UI for scrubbing preview 2020-05-01 19:43:47 -07:00
Linus Unnebäck
81b3d64f42 Use object shorthand for properties 2020-04-26 15:14:36 +01:00
Borewit
cf0cf79440 Merge pull request #1795 from webtorrent/greenkeeper/music-metadata-6.3.6
Greenkeeper/music metadata 6.3.6
2020-03-16 18:11:00 +01:00
greenkeeper[bot]
a8e6796002 chore(package): update lockfile package-lock.json 2020-03-11 07:37:52 +00:00
greenkeeper[bot]
f77aff6adf fix(package): update music-metadata to version 6.3.6
Closes #1774
2020-03-11 07:37:48 +00:00
Borewit
7fd028e5fa Merge pull request #1787 from dsernst/dynamic-copyright-year
Automatically keep the copyright year up-to-date
2020-02-09 14:15:31 +01:00
David Ernst
74f1be5452 Remove unnecessary parentheses 2020-02-08 12:37:48 -08:00
Borewit
77317aadc4 Merge pull request #1582 from dsernst/feature/sort-file-alphanumerically-1185
Context menu option to sort files by name
2020-02-08 12:01:55 +01:00
David Ernst
8eb2fb8d5d Automatically keep the copyright year up-to-date 2020-02-05 16:15:17 -08:00
David Ernst
58de27c484 Merge branch 'master' into feature/sort-file-alphanumerically-1185 2020-02-05 09:22:51 -08:00
David Ernst
185f5ec30b Remove unnecessary natsort dep 2020-02-05 09:17:58 -08:00
greenkeeper[bot]
351e890db5 chore(package): update lockfile package-lock.json 2020-01-16 00:28:55 +00:00
greenkeeper[bot]
6f2a00c785 chore(package): update cross-zip to version 3.0.0 2020-01-16 00:28:51 +00:00
Borewit
6f2aa86229 Merge pull request #1772 from webtorrent/greenkeeper/music-metadata-6.1.0
Update music metadata 6.1.0
2020-01-08 20:02:17 +01:00
Borewit
38aef81476 Add additional audio file extensions: MPEG-Layer-2, Musepack, Matroska audio, WavePack 2020-01-08 19:58:48 +01:00
Borewit
9dc3bb4f03 Pass FileInfo into music-metadata.parseStream() according API v6.
Update metadata if music-metadata parse method resolves.
2020-01-06 12:01:38 +01:00
Borewit
9291449737 Sync lock file 2020-01-06 11:01:04 +01:00
greenkeeper[bot]
98ee69d696 chore(package): update lockfile package-lock.json 2020-01-05 16:41:17 +00:00
greenkeeper[bot]
c5d20d56ec fix(package): update music-metadata to version 6.1.0
Closes #1749
2020-01-05 16:41:12 +00:00
Julen Garcia Leunda
e341367583 Merge pull request #1239 from SharonGrossman/feat/remove-all-torrents
feat(delete-all-torrents): added remove all torrents capability to the Transfers menu
2020-01-05 16:29:01 +01:00
Diego Rodríguez Baquero
f92a4c3e7d Merge pull request #1764 from hicom150/remove_deep_equal
Remove deep-equal dependency
2020-01-04 13:07:57 -05:00
Julen Garcia Leunda
5b894df71b fix lint errors 2019-12-19 18:34:35 +01:00
Julen Garcia Leunda
4577670fa8 Merge branch 'master' into feat/remove-all-torrents 2019-12-19 18:26:29 +01:00
Julen Garcia Leunda
6cac1f84ec Merge pull request #1757 from webtorrent/greenkeeper/semver-7.0.0
Update semver to the latest version 🚀
2019-12-19 17:46:05 +01:00
Julen Garcia Leunda
3c6b189ae6 Remove deep-equal dependency 2019-12-19 17:23:17 +01:00
greenkeeper[bot]
570145b2a4 chore(package): update lockfile package-lock.json 2019-12-14 20:06:27 +00:00
greenkeeper[bot]
95f2356b4c fix(package): update semver to version 7.0.0 2019-12-14 20:06:23 +00:00
Julen Garcia Leunda
97426621bf Fix windows installer event handler 2019-12-12 22:48:13 +01:00
Julen Garcia Leunda
3b7a9f9830 Merge pull request #1751 from hicom150/update_to_dialog_sync_functions
Fix deprecated dialog callback functions
2019-12-12 22:09:58 +01:00
Julen Garcia Leunda
61b92efcda Merge pull request #1746 from webtorrent/greenkeeper/application-config-2.0.0
Update application-config to the latest version 🚀
2019-12-06 17:17:25 +01:00
hicom150
b3026dbd87 Merge remote-tracking branch 'upstream/master' into update_application_config 2019-12-06 16:58:15 +01:00
hicom150
2eea86d8eb fix application-config update 2019-12-06 16:48:53 +01:00
Julen Garcia Leunda
46fb391d6c Merge pull request #1752 from hicom150/architectures
Show all supported architectures
2019-11-28 18:47:35 +01:00
Julen Garcia Leunda
79b3597637 Merge pull request #1740 from webtorrent/greenkeeper/electron-7.1.0
Update electron to the latest version 🚀
2019-11-28 17:23:45 +01:00
Julen Garcia Leunda
32dc268891 Merge pull request #1735 from akaustav/master
Fixed Material UI Getting Started link
2019-11-28 17:23:01 +01:00
Julen Garcia Leunda
02975e6b0e Merge branch 'master' into greenkeeper/electron-7.1.0 2019-11-28 17:21:23 +01:00
Julen Garcia Leunda
83dd5e35a7 Fix integration tests 2019-11-28 17:13:37 +01:00
Julen Garcia Leunda
1d6054f78b Merge pull request #1750 from webtorrent/greenkeeper/nodemon-2.0.0
Update nodemon to the latest version 🚀
2019-11-28 16:39:56 +01:00
Julen Garcia Leunda
8a947a2f80 Merge pull request #1748 from webtorrent/update-music-metadata
Update music-metadata to 4.9.2
2019-11-28 16:35:29 +01:00
Julen Garcia Leunda
6c22f5f595 show all supported architectures 2019-11-28 16:22:23 +01:00
Julen Garcia Leunda
bea86b2a67 Merge pull request #1743 from gpatarin/issue-1741-savetorrentas
Fix for issue #1741 (Save Torrent File As...)
2019-11-26 17:11:25 +01:00
Julen Garcia Leunda
82f873270e Merge pull request #1737 from akaustav/fix-about-window
Fix: Increase height of 'About' window
2019-11-26 17:01:50 +01:00
Julen Garcia Leunda
2b8fa8b6fe fix review comments 2019-11-26 16:59:10 +01:00
Julen Garcia Leunda
38390405dc Merge remote-tracking branch 'upstream/master' into fix-about-window 2019-11-26 16:55:44 +01:00
Gael Patarin
f30343b821 Added buttonLabel as Save in the save dialog 2019-11-26 14:33:47 +01:00
hicom150
d738021285 Fix deprecated dialog callback functions 2019-11-23 00:03:20 +01:00
greenkeeper[bot]
08e32dde7e chore(package): update lockfile package-lock.json 2019-11-20 16:03:51 +00:00
greenkeeper[bot]
229321c6c5 chore(package): update nodemon to version 2.0.0 2019-11-20 16:03:40 +00:00
Borewit
3b65f2a4a7 Update music-metadata to 4.9.2 2019-11-19 21:13:56 +01:00
Diego Rodríguez Baquero
93b0e42609 Merge pull request #1739 from webtorrent/greenkeeper/depcheck-0.9.0
Update depcheck to the latest version 🚀
2019-11-18 12:36:00 -05:00
Diego Rodríguez Baquero
633cdb4a82 Merge pull request #1742 from webtorrent/greenkeeper/languagedetect-2.0.0
Update languagedetect to the latest version 🚀
2019-11-18 12:33:47 -05:00
greenkeeper[bot]
eda0e0f964 chore(package): update lockfile package-lock.json 2019-11-16 18:01:35 +00:00
greenkeeper[bot]
a850cf6635 fix(package): update application-config to version 2.0.0 2019-11-16 18:01:31 +00:00
Feross Aboukhadijeh
af8b9cf1f2 Update drag-drop to the latest version 🚀 (#1744)
Update drag-drop to the latest version 🚀
2019-11-12 16:13:31 -08:00
greenkeeper[bot]
cc6cc41ad3 chore(package): update lockfile package-lock.json 2019-11-13 00:07:46 +00:00
greenkeeper[bot]
8228036936 fix(package): update drag-drop to version 6.0.0 2019-11-13 00:07:40 +00:00
gpatarin
600646b6ce Making the save file dialog sync to ensure working properly on MacOS and others 2019-11-09 23:58:43 +01:00
greenkeeper[bot]
fc73d2e6fd chore(package): update lockfile package-lock.json 2019-11-05 23:41:49 +00:00
greenkeeper[bot]
616cef87cb fix(package): update languagedetect to version 2.0.0 2019-11-05 23:41:45 +00:00
greenkeeper[bot]
fdc65d6e51 chore(package): update lockfile package-lock.json 2019-11-05 14:45:08 +00:00
greenkeeper[bot]
be922ef7c1 chore(package): update electron to version 7.1.0 2019-11-05 14:45:03 +00:00
greenkeeper[bot]
7dd5385f15 chore(package): update lockfile package-lock.json 2019-11-01 22:46:37 +00:00
greenkeeper[bot]
a5a199b63c chore(package): update depcheck to version 0.9.0 2019-11-01 22:46:32 +00:00
Ameet Kaustav
ab129fa233 Fix: Increase Height of 'About' window even more 2019-10-31 01:17:09 -07:00
Mathias Rasmussen
35717e9dfb Fix config copyright path in about window 2019-10-30 12:58:30 +01:00
Ameet Kaustav
a881668b38 Fix: Increase height of 'About' window 2019-10-29 22:28:07 -07:00
Ameet Kaustav
7e92647360 Fixed Material UI Getting Started link 2019-10-29 19:54:03 -07:00
Feross Aboukhadijeh
0198d7493d spectron@9 2019-10-23 13:23:34 -07:00
Feross Aboukhadijeh
04d9bc8752 Bump versions 2019-10-23 13:21:49 -07:00
Feross Aboukhadijeh
3e5fdcf6b9 Fixes for Electron 7 2019-10-23 13:19:24 -07:00
Feross Aboukhadijeh
d538a23ad0 Update electron to the latest version 🚀 (#1729)
Update electron to the latest version 🚀
2019-10-23 13:19:12 -07:00
Feross Aboukhadijeh
8de77e3d11 use org .github repo 2019-10-23 11:37:03 -07:00
greenkeeper[bot]
985def222e chore(package): update lockfile package-lock.json 2019-10-22 06:04:33 +00:00
greenkeeper[bot]
9bf4576a50 chore(package): update electron to version 7.0.0 2019-10-22 06:04:22 +00:00
Feross Aboukhadijeh
a5c41c8313 Update open to the latest version 🚀 (#1724)
Update open to the latest version 🚀
2019-10-19 12:56:42 -07:00
Julen Garcia Leunda
11d04d52c1 Merge pull request #1720 from webtorrent/type-issues
Fix a few type errors
2019-10-18 11:26:25 +02:00
greenkeeper[bot]
cb5af1a396 chore(package): update lockfile package-lock.json 2019-10-15 18:45:03 +00:00
greenkeeper[bot]
8a487cff9e chore(package): update open to version 7.0.0 2019-10-15 18:44:44 +00:00
Julen Garcia Leunda
45920e065e Merge pull request #1712 from hicom150/change_audio_tracks
Add support for multiple audio tracks
2019-10-13 22:54:59 +02:00
hicom150
2d7b6c01d0 Merge branch 'master' into change_audio_tracks 2019-10-13 22:38:50 +02:00
Julen Garcia Leunda
c33acd0746 Merge pull request #1711 from hicom150/fix_codec_unsupported_detection
Improve codec unsupported detection
2019-10-13 22:12:56 +02:00
hicom150
f2c531baa4 use videoTracks and audioTracks to check unsupported codecs 2019-10-12 17:44:13 +02:00
hicom150
287bcfd703 Merge branch 'master' into fix_codec_unsupported_detection 2019-10-11 16:56:34 +02:00
Mathias Rasmussen
e71555e664 Fix type errors 2019-10-09 19:34:30 +02:00
Borewit
bc921c889e Merge pull request #1719 from webtorrent/update-music-metadata
Update music-metadata to v4.8.0
2019-10-08 10:54:08 +02:00
Julen Garcia Leunda
59ebe132db Merge pull request #1707 from hicom150/no_sandbox
Add --no-sandbox option to desktop files
2019-10-07 22:57:04 +02:00
hicom150
b47d335e86 Merge branch 'fix_codec_unsupported_detection' of github.com:hicom150/webtorrent-desktop into fix_codec_unsupported_detection 2019-10-07 22:08:46 +02:00
hicom150
f5e186dc67 Apply review changes 2019-10-07 22:06:50 +02:00
hicom150
3d85803df9 Improve codec unsupported detection 2019-10-07 22:06:50 +02:00
Borewit
5c64fb5d35 Update music-metadata to v4.8.0 2019-10-07 20:01:19 +02:00
hicom150
5280fc76e9 Merge branch 'master' into fix_codec_unsupported_detection 2019-10-07 17:54:41 +02:00
hicom150
d4a8d9a120 Apply review changes 2019-10-07 17:54:36 +02:00
Feross Aboukhadijeh
3fbf33b8ae remove borewit from funding.yml (per his request) 2019-10-06 14:52:23 -07:00
hicom150
0d27223f16 Add support for multiple audio tracks 2019-10-06 22:10:35 +02:00
Feross Aboukhadijeh
2c5fcab469 Merge pull request #1717 from pR0Ps/feature/verification-status
Report when files are being verified
2019-10-06 11:04:35 -07:00
Carey Metcalfe
8fc7150559 Report when files are being verified
When starting a torrent that is partially-downloaded, WebTorrent will
now report "Verifying" as it verifies the existing data on disk.

Fixes #1586
2019-10-03 02:22:12 -04:00
Feross Aboukhadijeh
89b53ffe96 Merge pull request #1716 from pR0Ps/master
Floor individual file percentages for display
2019-10-01 06:49:42 -07:00
Feross Aboukhadijeh
e990bc898d mono is needed to create setup.exe (#1715)
mono is needed to create setup.exe
2019-09-30 21:49:09 -07:00
Feross Aboukhadijeh
cb699b5fec readme: clarify windows homebrew instructions 2019-09-30 21:48:56 -07:00
Lucas
8a235c31e0 mono is needed to create setup.exe 2019-10-01 11:05:53 +13:00
Carey Metcalfe
8ee27b8ef4 Floor individual file percentages for display
Fixes #1713
2019-09-26 20:49:17 -04:00
hicom150
5023651e63 Improve codec unsupported detection 2019-09-25 22:24:56 +02:00
Julen Garcia Leunda
f65fc68179 Add --no-sandbox option to desktop files 2019-09-19 22:41:34 +02:00
Feross Aboukhadijeh
b9bcf747de Set default externalPlayerPath (#1702)
Set default externalPlayerPath
2019-09-19 12:58:42 -07:00
Feross Aboukhadijeh
88e7167b6c Add rpm package creation support (#1694)
Add rpm package creation support
2019-09-19 12:56:14 -07:00
Pieter Goetschalckx
f5ab39be8e Migrate config file 2019-09-19 15:22:49 +02:00
Julen Garcia Leunda
6e69e5d36e Set correct architecture for RedHat based packages 2019-09-18 20:44:14 +02:00
Feross Aboukhadijeh
9c4ca25615 Handle null paths in path selector (#1704)
Handle null paths in path selector
2019-09-18 11:22:33 -07:00
Mathias Rasmussen
d15f40b22d handle null paths 2019-09-18 19:41:26 +02:00
Pieter Goetschalckx
1befac8d0e Set default externalPlayerPath 2019-09-18 13:34:39 +02:00
Julen Garcia Leunda
cfa1ebbea7 Merge branch 'master' into add_package_rpm 2019-09-16 22:13:41 +02:00
Feross Aboukhadijeh
2a679dd6e8 Add linux arm64 build (Fixes for PR #1650) (#1696)
Add linux arm64 build (Fixes for PR #1650)
2019-09-15 14:50:14 -07:00
Feross Aboukhadijeh
fce5f00925 Add buble compiler target chrome version (#1695)
Add buble compiler target chrome version
2019-09-15 12:36:14 -07:00
Feross Aboukhadijeh
39d04c4b2a Add linux arm64 build (Fixes for PR #1650) 2019-09-15 12:30:30 -07:00
Feross Aboukhadijeh
5688e4538c introduce linux arm64 support (#1650)
introduce linux arm64 support
2019-09-15 12:19:15 -07:00
Julen Garcia Leunda
4e18d4091a Add rpm package creation documentation 2019-09-15 20:30:41 +02:00
Julen Garcia Leunda
cfde3ee85d Add buble compiler target chrome version 2019-09-15 19:34:16 +02:00
Julen Garcia Leunda
1c343cb4c1 Add rpm package creation support 2019-09-15 19:16:03 +02:00
Дамјан Георгиевски
e3e490daa5 Merge branch 'master' into master 2019-09-15 18:25:43 +02:00
Feross Aboukhadijeh
d7783749ca Update test-add-torrent.js 2019-09-14 17:06:28 -07:00
Feross Aboukhadijeh
b07fc8285f 0.21.0 2019-09-14 16:44:47 -07:00
Feross Aboukhadijeh
6379356612 authors 2019-09-14 16:44:38 -07:00
Feross Aboukhadijeh
ee3768faf8 Merge branch 'fix-windows' 2019-09-14 16:42:56 -07:00
Feross Aboukhadijeh
8ff65412a3 readme: screenshots: 2018 MacBook Pro 13" 2019-09-14 16:42:40 -07:00
Feross Aboukhadijeh
cb930bef0b test: Update screenshots 2019-09-14 16:42:01 -07:00
Feross Aboukhadijeh
6a76554563 Fix "EPERM: operation not permitted, open 'C:\Users\account\App… (#1693)
Fix "EPERM: operation not permitted, open 'C:\Users\account\AppData\Local
2019-09-14 16:35:12 -07:00
Feross Aboukhadijeh
e72005e239 Remove cp-file, use copyFileSync instead 2019-09-14 16:32:38 -07:00
Feross Aboukhadijeh
54b1832007 remove prepublish script
We don't publish the desktop app to npm anymore
2019-09-14 14:36:52 -07:00
Feross Aboukhadijeh
e714e00223 Fix Windows npm install
Like `appdmg`, `electron-installer-debian` cannot be installed on Windows.
2019-09-14 14:35:05 -07:00
Feross Aboukhadijeh
6989484e7c Add note about homebrew deps for debian build
Fixes: https://github.com/webtorrent/webtorrent-desktop/issues/1689
2019-09-14 14:08:01 -07:00
Feross Aboukhadijeh
53164a058d bump deps 2019-09-12 11:14:33 -07:00
Borewit
f84078c865 Merge pull request #1580 from webtorrent/ignore-intellij-project-files
Ignore JetBrains IntelliJ IDEA project files
2019-09-12 08:30:12 +02:00
Feross Aboukhadijeh
7eda218e82 Store magnet URI once torrent has been parsed (#1686)
Store magnet URI once torrent has been parsed
2019-09-11 19:44:06 -07:00
Feross Aboukhadijeh
54b0c23f11 Replace nobin-debian-installer (#1682)
Replace `nobin-debian-installer`
2019-09-10 14:12:52 -07:00
Feross Aboukhadijeh
b34417b1fc add back removed log statement 2019-09-10 14:12:42 -07:00
Julen Garcia Leunda
40005351b5 Merge branch 'master' into replace_nobin_debian_installer 2019-09-10 23:05:39 +02:00
Julen Garcia Leunda
6255ccd253 Resolve requested changes 2019-09-10 22:54:34 +02:00
Feross Aboukhadijeh
4a10a2dfd1 Merge pull request #1679 from webtorrent/then
Use promise then() instead of catch() with callbacks
2019-09-10 11:05:12 -07:00
Feross Aboukhadijeh
992ab0bf10 electron-osx-sign@0.4.13 2019-09-10 10:33:53 -07:00
Feross Aboukhadijeh
83a2d090ff bump deps 2019-09-10 10:33:09 -07:00
Feross Aboukhadijeh
8133ce7b92 create-torrent@4.4.1 2019-09-10 10:31:32 -07:00
Feross Aboukhadijeh
6a07f705f7 Update package-lock.json 2019-09-10 10:31:29 -07:00
Feross Aboukhadijeh
9455912d98 Update airplayer dependency (#1680)
Update airplayer dependency
2019-09-10 10:27:28 -07:00
Feross Aboukhadijeh
052e0a4a31 Added 'Release notes' and 'follow on twitter' options in help (#1683)
Added 'Release notes' and 'follow on twitter' options in help
2019-09-10 09:59:22 -07:00
Chandan Chowdary Bhagam
b8b1ddc138 Added 'Release notes' and 'follow on twitter' options in help 2019-09-10 09:17:28 +00:00
Feross Aboukhadijeh
a92fee3532 Auto populate 'Magnet Link' field with the address from clipboa… (#1681)
Auto populate 'Magnet Link' field with the address from clipboard
2019-09-09 18:46:29 -07:00
Julen Garcia Leunda
aff402f6e0 Replace nobin-debian-installer 2019-09-09 22:52:26 +02:00
Daniele Debernardi
a39691fdad Auto populate 'Magnet Link' field with the address from clipboard
Co-authored-by: Jon Koops <jonkoops@gmail.com>
2019-09-09 21:41:07 +02:00
hicom150
7eecf709f9 Update airplayer dependency 2019-09-08 11:51:11 +02:00
Feross Aboukhadijeh
dd13de5f65 Use promise then() instead of catch() with callbacks
Addresses my review here: https://github.com/webtorrent/webtorrent-desktop/pull/1419#pullrequestreview-285182318
2019-09-07 11:13:26 -07:00
Feross Aboukhadijeh
647eaf5af9 #1667 rename dependency opn to open (#1677)
#1667 rename dependency opn to open
2019-09-06 12:48:36 -07:00
Borewit
24394a9028 #1667 rename dependency opn to open 2019-09-06 20:46:29 +02:00
Feross Aboukhadijeh
e8835c3054 package: Remove npm dedupe
We don't want to modify the package-lock.json file at packaging time.
2019-09-06 00:12:08 -07:00
Feross Aboukhadijeh
2834cca9fa package: use npm ci, remove npm dedupe
`npm ci` does not modify the package-lock.json file, which is exactly what we want during packaging time. Otherwise, on Windows, npm will attempt to remove the mac-only dependencies like appdmg from package-lock.json.
2019-09-06 00:11:52 -07:00
Feross Aboukhadijeh
744e720c3b Ignore play() when called before init()
If an error occurs during startup, then it's possible that we'll try to call sound.play('ERROR') in the error handler, which will throw an exception. Instead, just don't play sounds in this case.
2019-09-05 23:59:32 -07:00
Feross Aboukhadijeh
a6dfd98717 Depend on webtorrent/nobin-debian-installer fork
Fixes: https://github.com/grunjol/nobin-debian-installer/pull/8
Fixes: https://github.com/grunjol/nobin-debian-installer/pull/7
2019-09-05 23:13:41 -07:00
Feross Aboukhadijeh
4550f09bf1 authors 2019-09-05 22:18:00 -07:00
Feross Aboukhadijeh
7289e32bea Update package-lock.json 2019-09-05 22:18:00 -07:00
Feross Aboukhadijeh
0bdbe66d96 Change electron-packager from callback to promises (#1673)
Change electron-packager from callback to promises
2019-09-05 22:17:42 -07:00
Feross Aboukhadijeh
e58e701e2c appdmg@0.6.0
Fixes: https://github.com/webtorrent/webtorrent-desktop/pull/1593
2019-09-05 22:10:05 -07:00
Feross Aboukhadijeh
ac9b79c8ca Merge pull request #1657 from hicom150/update_spectron
Fix integration test setup

Co-authored-by: null <23040076+greenkeeper[bot]@users.noreply.github.com>
Co-authored-by: Feross Aboukhadijeh <feross@feross.org>
2019-09-05 21:55:27 -07:00
Feross Aboukhadijeh
280fbc1e8d Merge branch 'master' into update_spectron 2019-09-05 21:54:05 -07:00
Feross Aboukhadijeh
a1d4f706f7 Change electron-packager from callback to promises (#1660)
Change electron-packager from callback to promises
2019-09-05 21:47:44 -07:00
Feross Aboukhadijeh
6e2ff6887d Merge pull request #1642 from webtorrent/remove-32
Stop shipping 32-bit binaries
2019-09-05 21:45:52 -07:00
Feross Aboukhadijeh
fe297d4c56 Fixes for PR #1654 2019-09-05 21:42:12 -07:00
Feross Aboukhadijeh
b16971491f Merge branch 'master' of https://github.com/jimmywarting/webtorrent-desktop into jimmywarting 2019-09-05 21:39:19 -07:00
Feross Aboukhadijeh
4b1866d521 electron-winstaller@4 2019-09-05 21:22:47 -07:00
Feross Aboukhadijeh
c539375adc update deps 2019-09-05 21:18:52 -07:00
Feross
ec8beda1ed Merge pull request #1666 from webtorrent/update-deps
Update dependencies (prep for release)
2019-09-05 12:18:55 -07:00
Feross Aboukhadijeh
cd96986445 package.json: bump deps to use latest version
This doesn't actually change package-lock.json in a meaningful way. But I want package.json to list the latest version.
2019-09-04 17:28:15 -07:00
Feross Aboukhadijeh
975e57d57b update castv2 dependency to fix npm audit warning
For: https://github.com/webtorrent/webtorrent-desktop/issues/1599
2019-09-04 16:58:08 -07:00
Feross Aboukhadijeh
08ad4f73f1 music-metadata@4.5.0 2019-09-04 16:54:16 -07:00
Feross Aboukhadijeh
c9f9c868df electron@6.0.7 2019-09-04 16:52:11 -07:00
Feross Aboukhadijeh
e7f8f4ccfc react@16.9.0, react-dom@16.9.0 2019-09-04 16:48:11 -07:00
Feross Aboukhadijeh
e1b0c85778 iso-639-1@2.1.0 2019-09-04 16:44:47 -07:00
Feross Aboukhadijeh
2148d98f3a electron-packager@14.0.5 2019-09-04 16:44:10 -07:00
Feross Aboukhadijeh
d06508fda6 create-torrent@4.3.0 2019-09-04 16:43:17 -07:00
Feross Aboukhadijeh
1f780fc307 npm dedupe 2019-09-04 16:42:52 -07:00
Feross Aboukhadijeh
0178e9dcb8 bitfield@3 2019-09-04 16:41:50 -07:00
Feross Aboukhadijeh
c170c247a9 cross-zip@2.1.6 2019-09-04 16:40:01 -07:00
Feross Aboukhadijeh
4bb3edbf8d deep-equal@1.1.0 2019-09-04 16:39:39 -07:00
Feross Aboukhadijeh
9dbae636ae nodemon@1.19.2 2019-09-04 16:36:46 -07:00
Feross Aboukhadijeh
b6234f7705 vlc-command@1.2.0 2019-09-04 16:36:06 -07:00
Feross Aboukhadijeh
101dd356ae webtorrent@>=0.107.6
To address minor xss vulnerability in http server. See: https://github.com/webtorrent/webtorrent/pull/1714
2019-09-04 16:35:43 -07:00
Feross Aboukhadijeh
f8e9db25cd funding: add borewit 2019-09-04 14:50:14 -07:00
Feross Aboukhadijeh
8e33507839 fixed by bumping babel-eslint 2019-08-28 22:49:36 -07:00
Feross Aboukhadijeh
4c4c3508c2 Merge pull request #1664 from webtorrent/greenkeeper/drag-drop-5.0.1
Greenkeeper/drag drop 5.0.1
2019-08-28 13:14:07 -07:00
greenkeeper[bot]
a7ec8ba04e chore(package): update lockfile package-lock.json 2019-08-28 20:04:57 +00:00
greenkeeper[bot]
b5dce351b0 fix(package): update drag-drop to version 5.0.1
Closes #1663
2019-08-28 20:04:53 +00:00
Julen Garcia Leunda
59fa19d7ad Change electron-packager from callback to promises 2019-08-20 23:22:11 +02:00
hicom150
619e5249ac Fix integration test setup 2019-08-19 16:27:21 +02:00
greenkeeper[bot]
48340010b1 chore(package): update lockfile package-lock.json 2019-08-19 16:27:21 +02:00
greenkeeper[bot]
4599752d9d chore(package): update spectron to version 8.0.0
Closes #1609
2019-08-19 16:27:21 +02:00
Feross Aboukhadijeh
5eec89cd42 Merge pull request #1658 from webtorrent/music-metadata-v4.3
Update dependency music-metadata to v4.3.0
2019-08-18 14:22:10 -07:00
Borewit
dcecab2d9f Update dependency music-metadata to v4.3.0; improve decoding MPEG-4-ADTS/AAC. 2019-08-18 22:09:02 +02:00
Feross Aboukhadijeh
767d31ebd8 Merge pull request #1498 from webtorrent/cleanup-preferences
Cleanup preferences page
2019-08-18 12:30:50 -07:00
Feross Aboukhadijeh
1ece5de579 add discord link 2019-08-18 10:16:20 -07:00
Mathias Rasmussen
f34a79df36 path-selector: display path instead of name 2019-08-17 22:23:05 +02:00
Mathias Rasmussen
f231c54886 clean up preferences-page 2019-08-17 22:23:05 +02:00
Jimmy Wärting
56f0826928 remove zero fill at the final place
supersede #1583
2019-08-16 22:27:37 +02:00
Feross Aboukhadijeh
caceeee238 Merge pull request #1583 from jimmywarting/patch-1
Removed zero-fill
2019-08-16 11:49:38 -07:00
Feross Aboukhadijeh
afd3b84b40 Fixes for PR #1648 2019-08-15 13:10:39 -07:00
Feross Aboukhadijeh
4b927832c2 Merge pull request #1648 from hicom150/pass_title_metadata
Pass title metadata in media url
2019-08-15 13:08:59 -07:00
Feross Aboukhadijeh
c5679d546e chokidar@3
Fixes: https://github.com/webtorrent/webtorrent-desktop/pull/1576
2019-08-15 13:00:40 -07:00
hicom150
097fa9cc7c Add file name to state 2019-08-15 12:06:22 +02:00
Feross Aboukhadijeh
6f1a94359f standard 2019-08-14 17:52:55 -07:00
Feross Aboukhadijeh
44e2f366ce standard 2019-08-14 17:09:07 -07:00
Feross Aboukhadijeh
cf6b46364c standard 2019-08-14 17:07:33 -07:00
Дамјан Георгиевски
b8f7880a78 introduce linux arm64 support 2019-08-15 01:50:47 +02:00
Feross Aboukhadijeh
85c6816c23 standard 2019-08-14 16:29:25 -07:00
Feross Aboukhadijeh
0c1d7d6e0f standard 2019-08-14 16:21:14 -07:00
Feross Aboukhadijeh
3f073e083e standard 2019-08-14 16:13:07 -07:00
Feross Aboukhadijeh
6ce7e662c6 Merge pull request #1649 from webtorrent/greenkeeper/rimraf-3.0.0
Update rimraf to the latest version 🚀
2019-08-14 13:13:12 -07:00
greenkeeper[bot]
1e6c067139 chore(package): update lockfile package-lock.json 2019-08-14 18:18:26 +00:00
greenkeeper[bot]
f53038f6e9 fix(package): update rimraf to version 3.0.0 2019-08-14 18:18:02 +00:00
Feross Aboukhadijeh
c61234dd4c standard 2019-08-13 20:32:42 -07:00
Feross Aboukhadijeh
6336bbd6e3 use org-wide contributing file, move release process to new file 2019-08-13 15:15:43 -07:00
Feross Aboukhadijeh
649ac1900b use org-wide security file 2019-08-13 15:15:43 -07:00
Feross Aboukhadijeh
27e3d33f7d Use org-wide contributing file 2019-08-13 15:15:43 -07:00
hicom150
c29deab728 Pass title metadata in media url 2019-08-13 23:53:37 +02:00
Feross Aboukhadijeh
3a4ba6af37 Merge pull request #1641 from webtorrent/electron-6
Update to Electron 6
2019-08-13 13:05:56 -07:00
Feross Aboukhadijeh
e49d80fb17 Merge pull request #1646 from hicom150/fix_clean
Fix uninstall handlers in Linux
2019-08-12 12:18:52 -07:00
hicom150
a37f00bc10 Fix uninstall handlers in Linux 2019-08-12 10:29:30 +02:00
Feross Aboukhadijeh
925d495b62 remove stray console.log 2019-08-09 15:04:07 -07:00
Feross Aboukhadijeh
809beb4f81 Remove consistent JSX tag closing check
StandardJS is getting this rule in standard v14.
2019-08-09 15:03:06 -07:00
Feross Aboukhadijeh
0359451498 Update to Electron 6 2019-08-09 15:03:06 -07:00
Feross Aboukhadijeh
f6bd2cfcf4 Merge pull request #1643 from webtorrent/electron-5
Update to Electron 5
2019-08-09 15:02:49 -07:00
Feross Aboukhadijeh
9eecc2410c Stop shipping 32-bit binaries
For: https://github.com/webtorrent/webtorrent-desktop/issues/1637
2019-08-07 10:29:41 -07:00
Feross Aboukhadijeh
6cd8af91be Update to Electron 5 2019-08-07 10:24:31 -07:00
Feross Aboukhadijeh
7a3c1f0a10 Merge pull request #1634 from webtorrent/electron-packager
electron-packager@^14.0.4
2019-08-07 10:21:31 -07:00
Feross Aboukhadijeh
f2f3558cc4 Update lock.yml 2019-08-05 16:00:26 -07:00
Feross Aboukhadijeh
0dfaf6c1cf Update lock.yml 2019-08-05 15:58:04 -07:00
Feross Aboukhadijeh
a6ecba8e13 Merge pull request #1635 from webtorrent/changelog-v0.21
Update changelog for v0.21.0
2019-08-04 11:41:46 -07:00
Feross Aboukhadijeh
1a2c507d47 Update config.yml 2019-08-04 10:18:47 -07:00
Feross Aboukhadijeh
95b61826e0 Update stale.yml 2019-08-04 10:16:14 -07:00
Feross Aboukhadijeh
b1da72fde8 Merge pull request #1603 from refreex/original
Changed function name handlesoundNotificationsChange for handleSoundNotificationsChange
2019-08-04 09:37:47 -07:00
Feross Aboukhadijeh
b5e64a390a Merge pull request #1607 from webtorrent/music-metadata-4.1
Update music-metadata to version 4.2
2019-08-04 09:36:58 -07:00
Mathias Rasmussen
da829e0d69 resolve package-lock conflicts 2019-08-04 18:08:47 +02:00
Mathias Rasmussen
fd02908afa Update changelog for v0.21.0 2019-08-04 17:02:52 +02:00
Feross Aboukhadijeh
38092fa055 Update no-response.yml 2019-08-03 22:13:47 -07:00
Feross Aboukhadijeh
24a7e060f2 electron-packager@^14.0.4 2019-08-03 21:54:04 -07:00
Feross Aboukhadijeh
bd962d4d76 Create .npmrc
Helps primarily module developers (like me) who set their local .npmrc to package-lock=false
2019-08-03 21:23:49 -07:00
Feross Aboukhadijeh
a54dbc42e9 Update package-lock.json 2019-08-03 21:23:16 -07:00
Borewit
4c2381db26 Merge pull request #1590 from webtorrent/update-electron
Update to electron 4; it may not be perfect, but we have to move on
2019-07-30 21:44:22 +02:00
Feross Aboukhadijeh
91400ae31c standard 2019-07-27 18:33:46 -07:00
Feross Aboukhadijeh
c8f1e23b1a standard 2019-07-27 16:27:52 -07:00
Borewit
188f1cac8f Merge branch 'master' into update-electron
# Conflicts:
#	package-lock.json
#	package.json
2019-07-21 10:44:11 +02:00
Borewit
b216929dc4 Comply with max 100 chars per line lint rule. 2019-07-21 10:37:16 +02:00
Borewit
08008bb25c #1590 Improve single-instance start-up logic, remove duplicate code. 2019-07-21 10:19:36 +02:00
Feross Aboukhadijeh
c96f212726 Update package-lock.json 2019-07-20 23:12:03 -07:00
Feross Aboukhadijeh
80c1a61c33 Merge pull request #1605 from webtorrent/greenkeeper/babel-eslint-10.0.2
Update babel-eslint to the latest version 🚀
2019-07-20 22:54:41 -07:00
Borewit
7925e04834 Merge remote-tracking branch 'origin/greenkeeper/music-metadata-4.2.0' into music-metadata-4.1
# Conflicts:
#	package.json
2019-07-11 19:11:44 +02:00
Feross Aboukhadijeh
4da9da3d9a Merge pull request #1620 from webtorrent/greenkeeper/walk-sync-2.0.2
Greenkeeper/walk sync 2.0.2
2019-07-10 10:15:09 -07:00
Feross Aboukhadijeh
9916073a98 Merge pull request #1540 from RecoX/patch-1
Recommended readings to start working in the app.
2019-07-10 09:52:03 -07:00
Feross Aboukhadijeh
820776427b Merge pull request #1585 from webtorrent/greenkeeper/depcheck-0.8.0
Update depcheck to the latest version 🚀
2019-07-10 09:51:04 -07:00
greenkeeper[bot]
da76ff53ce chore(package): update lockfile package-lock.json 2019-07-09 22:43:22 +00:00
greenkeeper[bot]
9a657bdc10 chore(package): update walk-sync to version 2.0.2
Closes #1610
2019-07-09 22:43:17 +00:00
Feross Aboukhadijeh
df73ba2512 Merge pull request #1618 from webtorrent/greenkeeper/capture-frame-3.0.0
Update capture-frame to the latest version 🚀
2019-07-08 18:04:45 -07:00
greenkeeper[bot]
450237052c chore(package): update lockfile package-lock.json 2019-07-06 07:02:19 +00:00
greenkeeper[bot]
ffde524c85 fix(package): update capture-frame to version 3.0.0 2019-07-06 07:02:16 +00:00
Feross Aboukhadijeh
2618548fbe Merge pull request #1617 from webtorrent/greenkeeper/parse-torrent-7.0.0
Update parse-torrent to the latest version 🚀
2019-07-05 15:19:11 -07:00
Feross Aboukhadijeh
0471d141c4 standard 2019-07-05 15:06:27 -07:00
greenkeeper[bot]
8b31c0376c chore(package): update lockfile package-lock.json 2019-07-05 21:45:43 +00:00
greenkeeper[bot]
10c23104a1 fix(package): update parse-torrent to version 7.0.0 2019-07-05 21:45:40 +00:00
Feross Aboukhadijeh
9ed3533225 standard 2019-07-05 14:26:38 -07:00
Recox
97342951d0 Merge branch 'master' of https://github.com/webtorrent/webtorrent-desktop into original 2019-07-02 21:06:01 +12:00
Feross Aboukhadijeh
46d50ccda2 Merge pull request #1612 from webtorrent/greenkeeper/create-torrent-4.0.0
Update create-torrent to the latest version 🚀
2019-06-28 17:09:39 -07:00
greenkeeper[bot]
290027b5c5 chore(package): update lockfile package-lock.json 2019-06-28 23:57:54 +00:00
greenkeeper[bot]
f6129444f7 fix(package): update create-torrent to version 4.0.0 2019-06-28 23:57:51 +00:00
greenkeeper[bot]
57189c0d06 fix(package): update music-metadata to version 4.2.0
Closes #1611
2019-06-27 20:29:31 +00:00
Borewit
0aaeea4d3c Update music-metadata to version ^4.1.1 and adapt to API changes 2019-06-18 20:40:59 +02:00
Borewit
f59a54782a Fix processing arguments from second instance 2019-06-17 21:05:37 +02:00
greenkeeper[bot]
4156a3f546 chore(package): update lockfile package-lock.json 2019-06-17 14:22:03 +00:00
greenkeeper[bot]
13edc02440 chore(package): update babel-eslint to version 10.0.2 2019-06-17 14:21:56 +00:00
Borewit
cb4fa201f0 Merge pull request #1597 from dsernst/electron-4-detached-devtools
Electron 4: Migrate .openDevTools() for new 'detach' pattern
2019-06-17 09:36:49 +02:00
Recox
1905f8fec9 Changed function name handleSoundNotificationsChange 2019-06-11 21:32:19 +12:00
Borewit
d45e3f3e7b Merge pull request #1596 from dsernst/electron-4-titlebar
Fix hiddenInset (Mac) titlebar style for electron 4
2019-06-04 07:01:49 +02:00
David Ernst
a039cbf348 Electron 4: Migrate .openDevTools() for new 'detach' pattern 2019-06-03 21:52:06 -07:00
David Ernst
c5a21bddfd Fix hiddenInset (Mac) titlebar style for electron 4 2019-06-03 20:47:05 -07:00
Borewit
c204b7a82c onAppOpen seems to be no longer in use. 2019-05-15 19:54:13 +02:00
Borewit
f475975b40 Adjust single instance call to comply with Electron 4 2019-05-15 19:43:14 +02:00
Borewit
d3031ecff2 Merge branch 'greenkeeper/electron-4.0.0' into update-electron
# Conflicts:
#	package.json
2019-05-15 17:31:37 +02:00
Borewit
9a0a2111d3 Merge pull request #1309 from bilelmoussaoui/patch-2
Fix the desktop file
2019-05-12 20:18:20 +02:00
Borewit
d0053dc2f4 Merge pull request #1536 from adriantombu/feature/sound-option
Toggle the sound notifications
2019-05-12 20:03:14 +02:00
greenkeeper[bot]
60e9bf461c chore(package): update lockfile package-lock.json 2019-05-08 14:07:18 +00:00
greenkeeper[bot]
6add81add8 chore(package): update depcheck to version 0.8.0 2019-05-08 14:07:11 +00:00
Jimmy Wärting
a16b5b5add Removed zero-fill
sets the version the same way webtorrent dose

f8923a66a8/index.js (L27-L29)
2019-05-08 13:55:34 +02:00
David Ernst
aab918ff1a Fix lint error (Line >100 chars) 2019-05-06 16:23:50 -07:00
David Ernst
ca97413b76 Update package-lock.json for natsort 2019-05-06 16:00:23 -07:00
Borewit
8b0b5f3738 Merge pull request #1579 from dsernst/playback-hotkeys-hicom150
Add YouTube style hotkeys. Closes #1395
2019-05-06 19:40:07 +02:00
David Ernst
07816f7470 Add f=fullscreen hotkey 2019-05-06 09:58:47 -07:00
Borewit
28bf22a710 Ignore JetBrains IntelliJ IDEA project files 2019-05-05 11:39:25 +02:00
David Ernst
2466b2e0a6 Add context menu option to toggle Sort by Name 2019-05-04 22:39:27 -07:00
David Ernst
2dc2953831 Merge branch 'master' into feature/sort-file-alphanumerically-1185 2019-05-04 22:03:59 -07:00
David Ernst
103a5026f9 Add YouTube style hotkeys. Closes #1395 2019-05-04 21:04:41 -07:00
Borewit
c7ef42a65e Merge pull request #1573 from webtorrent/small-updates
Small updates
2019-04-28 21:55:58 +02:00
Alberto Miranda
ccaf73a477 Added missing dots for supported media extensions. 2019-04-28 16:00:43 -03:00
Borewit
dae57b5507 Merge remote-tracking branch 'origin/greenkeeper/opn-6.0.0' into small-updates 2019-04-25 20:05:58 +02:00
Borewit
5dc1ffb70e Merge branch 'pr-1562' into small-updates 2019-04-25 19:55:37 +02:00
Borewit
1dc500d4f3 Merge branch 'pr-1546' into small-updates 2019-04-25 19:54:25 +02:00
Borewit
d9bb625534 Merge remote-tracking branch 'origin/greenkeeper/depcheck-0.7.2' into small-updates
# Conflicts:
#	package-lock.json
2019-04-25 19:51:29 +02:00
Borewit
47cb6b9d5b Merge remote-tracking branch 'origin/greenkeeper/walk-sync-1.1.3' into small-updates 2019-04-25 19:48:34 +02:00
Borewit
b1eed5122a Merge remote-tracking branch 'origin/greenkeeper/semver-6.0.0' into small-updates 2019-04-25 19:47:39 +02:00
Borewit
97801c4fef Merge remote-tracking branch 'origin/greenkeeper/iso-639-1-2.0.5' into small-updates 2019-04-25 19:45:17 +02:00
Borewit
77d2abe04e Merge remote-tracking branch 'origin/greenkeeper/cp-file-7.0.0' into small-updates 2019-04-25 19:43:00 +02:00
Borewit
8b78e29827 Update lock file 2019-04-25 19:42:48 +02:00
Borewit
e6bfc57fc4 Add DSD audio media extensions for Sony DSF (DSD Stream Format) & Philips DSDIFF (Direct Stream Digital Interchange File Format
Related: https://github.com/Borewit/music-metadata/releases/tag/v3.6.0
2019-04-25 08:46:06 +02:00
Borewit
7facf4f6a2 Update music-metadata tp version 3.6.1 2019-04-25 08:45:53 +02:00
Borewit
79c25ffb33 Update lock file 2019-04-24 19:56:57 +02:00
greenkeeper[bot]
24dca39177 chore(package): update lockfile package-lock.json 2019-04-19 13:41:01 +00:00
greenkeeper[bot]
d209c02886 fix(package): update cp-file to version 7.0.0 2019-04-19 13:40:56 +00:00
David Ernst
c3315ab0fc Remove reference to (BETA) in test comments 2019-04-07 00:08:19 -05:00
David Ernst
109803e802 Remove '(BETA)' from app window title 2019-04-06 23:51:29 -05:00
greenkeeper[bot]
43ddbc7fd9 chore(package): update lockfile package-lock.json 2019-04-02 02:15:21 +00:00
greenkeeper[bot]
c8af0d3c1d fix(package): update iso-639-1 to version 2.0.5 2019-04-02 02:15:17 +00:00
greenkeeper[bot]
7db9e920de chore(package): update lockfile package-lock.json 2019-03-27 10:43:08 +00:00
greenkeeper[bot]
c8b726c0d1 fix(package): update semver to version 6.0.0
Closes #1559
2019-03-27 10:43:03 +00:00
greenkeeper[bot]
180acc15cd chore(package): update lockfile package-lock.json 2019-03-27 08:12:50 +00:00
greenkeeper[bot]
c3d261c74a chore(package): update opn to version 6.0.0 2019-03-27 08:12:46 +00:00
Feross Aboukhadijeh
0db89109a5 Remove NSP link 2019-03-25 22:23:43 -07:00
Diego Rodríguez Baquero
6ee0476799 Merge pull request #1531 from webtorrent/music-metadata-3.4.1
Update music-metadata to 3.5.2
2019-03-07 10:56:21 -05:00
Borewit
d86da0b0f7 Update music-metadata to 3.5.2, addressed sinificant performance issue handling MP3's. 2019-03-07 08:35:15 +01:00
greenkeeper[bot]
eb483ccd48 chore(package): update lockfile package-lock.json 2019-02-28 20:55:59 +00:00
greenkeeper[bot]
e7d5af5944 chore(package): update depcheck to version 0.7.2 2019-02-28 20:55:55 +00:00
David Ernst
0e3962e3f6 Update copyright for 2019 2019-02-23 00:09:42 -08:00
greenkeeper[bot]
992de4d80e chore(package): update lockfile package-lock.json 2019-02-05 03:46:35 +00:00
greenkeeper[bot]
85586d2dc5 chore(package): update walk-sync to version 1.1.3 2019-02-05 03:46:30 +00:00
Lucas
21ee5566a7 Update README.md 2019-01-31 11:48:37 +13:00
Lucas
429a376ccf Recommended readings to start working in the app.
As there is no too much information in the readme.md in how is this made, I think put a link of Electron and React to have an idea of the technologies used here is a good starter.
2019-01-31 11:41:31 +13:00
Mathias Rasmussen
a48c09e688 migrate sound option 2019-01-13 22:25:11 +01:00
Adrian Tombu
03de09fcaf Preference page cleaning 2019-01-13 11:17:46 +01:00
Adrian Tombu
97cf38e501 Toggle the sound notifications 2019-01-12 12:54:06 +01:00
Borewit
c24c99de36 Update music-metadata to 3.4.1 2019-01-01 17:33:08 +01:00
greenkeeper[bot]
a1ab889fca chore(package): update electron to version 4.0.0
Closes #1523
2018-12-21 00:36:42 +00:00
Borewit
170fd28c55 Merge pull request #1514 from webtorrent/greenkeeper/music-metadata-3.2.2
Greenkeeper/music metadata 3.3.0
2018-12-17 21:36:59 +01:00
Borewit
cdf5c5364a Merge branch 'master' into greenkeeper/music-metadata-3.2.2
# Conflicts:
#	package-lock.json
2018-12-16 17:15:16 +01:00
Borewit
2e85b4041f Updated music-metadata to v3.3.0. 2018-12-16 16:40:36 +01:00
Diego Rodríguez Baquero
a56e14f0a0 Merge pull request #1483 from webtorrent/update-material-ui
Update React and Material-UI
2018-12-12 14:28:46 -05:00
Mathias Rasmussen
16c3476960 update lockfile 2018-12-12 04:31:43 +01:00
Mathias Rasmussen
982ef3ae97 fix another unique key issue 2018-12-12 04:31:36 +01:00
Mathias Rasmussen
6057751e99 update react 2018-12-12 04:25:59 +01:00
Mathias Rasmussen
4c715111c5 fix react unique keys 2018-12-12 04:25:59 +01:00
Mathias Rasmussen
0d8e9792ff use react prop-types module 2018-12-12 04:25:59 +01:00
Mathias Rasmussen
ba5ccdb5cb update to material-ui 0.20.2
remove react-tap-event-plugin, as it is not needed anymore.
2018-12-12 04:25:59 +01:00
Mathias Rasmussen
579ca908c6 Merge pull request #1485 from webtorrent/update-auto-launch
Update auto-launch
2018-12-12 04:15:46 +01:00
Mathias Rasmussen
c7d7148132 update electron 2018-12-12 03:53:47 +01:00
Mathias Rasmussen
18ad5b0a01 Update dependencies 2018-12-12 03:48:01 +01:00
Mathias Rasmussen
cde3298920 update auto-launch 2018-12-12 03:37:06 +01:00
Borewit
20e3fb6f5f Add aif/aiff, spx (Speex) & mpc (Musepack) as audio file extensions.
Remove clashing .mp4 extension (with video) from audio.
2018-11-20 09:06:02 +01:00
greenkeeper[bot]
f0b87db248 chore(package): update lockfile package-lock.json 2018-11-19 19:50:48 +00:00
greenkeeper[bot]
2d90b29612 chore(package): update music-metadata to version 3.2.2 2018-11-19 19:50:44 +00:00
Borewit
81e6d7f3a7 Merge pull request #1506 from webtorrent/bnjmnt4n/playback-times
Ensure that the minutes field in playback indicator is zero-padded.
2018-11-06 18:37:01 +01:00
Benjamin Tan
a676a20054 Ensure that the minutes field in playback indicator is zero-padded.
The minutes field should be zero-padded as long as the playback media is longer than 9 minutes (including hours).

Fixes #1438.
2018-11-04 13:27:30 +08:00
Mathias Rasmussen
aef5669b76 Merge pull request #1497 from LinusU/prefer-const
Prefer const over let
2018-10-11 19:11:18 +02:00
Linus Unnebäck
ffb809bbca Prefer const over let 2018-10-10 21:21:29 +02:00
Mathias Rasmussen
60862ec01d refactor torrent-list-controller 2018-10-08 01:52:21 +02:00
Sharon Grossman
b7fedb1983 feat(delete-all-torrents): added remove all torrents capability to the Transfers menu 2018-10-08 01:52:21 +02:00
Bilal Elmoussaoui
c990738c57 Fix the desktop file 2018-01-20 10:19:23 +01:00
Cezar Carneiro
ab41d55e4b fix ETA and reorganize 2017-08-02 22:52:45 -03:00
Cezar Carneiro
739e7a50f7 improve infos 2017-08-02 00:03:52 -03:00
Cezar Carneiro
64ff5ebfd5 show percentage, size, speed and peers 2017-07-31 22:47:53 -03:00
Egor Yurtaev
2aa2f0de19 Sort files alphanumerically #1185 2017-06-24 22:09:42 +06:00
Adam Gotlib
d631ed1cc7 Store magnet URI once torrent has been parsed
Fixes #1035.
2016-10-15 17:00:03 +02:00
130 changed files with 26171 additions and 10309 deletions

View File

@@ -1,11 +0,0 @@
<!-- DO NOT POST LINKS OR REFERENCES TO COPYRIGHTED CONTENT IN YOUR ISSUE. -->
**What version of WebTorrent Desktop?** (See the 'About WebTorrent' menu)
**What operating system and version?**
**What did you do?**
**What did you expect to happen?**
**What actually happened?**

20
.github/ISSUE_TEMPLATE/BUG_REPORT.md vendored Normal file
View File

@@ -0,0 +1,20 @@
---
name: "🐞 Bug report"
about: Report an issue with this software
title: ''
labels: ''
assignees: ''
---
<!-- DO NOT POST LINKS OR REFERENCES TO COPYRIGHTED CONTENT IN YOUR ISSUE. -->
**What version of WebTorrent Desktop are you using?**
**What operating system and version?**
**What happened?**
**What did you expect to happen?**
**Are you willing to submit a pull request to fix this bug?**

View File

@@ -0,0 +1,20 @@
---
name: "⭐️ Feature request"
about: Request a new feature to be added
title: ''
labels: ''
assignees: ''
---
<!-- DO NOT POST LINKS OR REFERENCES TO COPYRIGHTED CONTENT IN YOUR ISSUE. -->
**What version of WebTorrent Desktop are you using?**
**What operating system and version?**
**What problem do you want to solve?**
**What do you think is the correct solution to this problem?**
**Are you willing to submit a pull request to implement this change?**

19
.github/config.yml vendored
View File

@@ -1,19 +0,0 @@
# ProBot Request Info (https://probot.github.io/apps/request-info/)
requestInfoReplyComment: >
👋 We would appreciate it if you could provide us with more information about this
issue. <br><br> ![](https://feross.net/s/cats/14.gif)
requestInfoLabelToAdd: 'need more info'
# ProBot Welcome (https://probot.github.io/apps/welcome/)
newPRWelcomeComment: >
🙌 Thanks for opening this pull request! You're awesome.
<br><br> ![](https://feross.net/s/cats/6.gif)
firstPRMergeComment: >
🎉 Congrats on getting your first pull request landed! <br><br>
![](https://feross.net/s/cats/29.gif)
# ProBot WIP (https://probot.github.io/apps/wip/)
# (Requires no configuration)

4
.github/lock.yml vendored
View File

@@ -1,4 +0,0 @@
# ProBot Lock (https://probot.github.io/apps/lock/)
daysUntilLock: 90
lockComment: false

View File

@@ -1,9 +0,0 @@
# ProBot No Response (https://probot.github.io/apps/no-response/)
daysUntilClose: 7
responseRequiredLabel: 'need more info'
closeComment: >
This issue has been automatically closed because there was no response to a
request for more information from the issue opener. Please leave a comment or
open a new issue if you have additional information related to this issue.
<br><br> ![](https://feross.net/s/cats/7.gif)

14
.github/stale.yml vendored
View File

@@ -1,14 +0,0 @@
# ProBot Stale (https://probot.github.io/apps/stale/)
daysUntilStale: 90
daysUntilClose: 7
exemptLabels:
- accepted
- bug
- enhancement
- meta
staleLabel: stale
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs.
closeComment: false

21
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: ci
on: [push,pull_request]
jobs:
test:
name: Node ${{ matrix.node }} / ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
node:
- '16'
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node }}
- run: npm install
- run: npm run build --if-present
- run: npm test

69
.github/workflows/package.yml vendored Normal file
View File

@@ -0,0 +1,69 @@
name: package
on:
workflow_dispatch:
jobs:
package_linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v6
with:
node-version: '16'
- uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- run: npm install
- run: npm run package -- linux
- uses: actions/upload-artifact@v3
with:
name: linux
path: |
dist/*.deb
dist/*.rpm
dist/*.zip
package_macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v6
with:
node-version: '16'
- uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- run: npm install
- run: npm run package -- darwin
- uses: actions/upload-artifact@v3
with:
name: macos
path: |
dist/*.dmg
dist/*.zip
package_windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v6
with:
node-version: '16'
- uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- run: npm install
- run: npm run package -- win32
- uses: actions/upload-artifact@v3
with:
name: windows
path: |
dist/*.exe
dist/*.nupkg
dist/*.zip

23
.github/workflows/stale.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: Mark stale issues and pull requests
on:
schedule:
- cron: '0 12 * * *'
jobs:
stale:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v6
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'Is this still relevant? If so, what is blocking it? Is there anything you can do to help move it forward?'
stale-pr-message: 'Is this still relevant? If so, what is blocking it? Is there anything you can do to help move it forward?'
exempt-issue-labels: accepted,blocked,dependency,security,meta
exempt-pr-labels: accepted,blocked,bug,dependency,security,meta
stale-issue-label: 'stale'
stale-pr-label: 'stale'

5
.gitignore vendored
View File

@@ -2,3 +2,8 @@ node_modules/
build/
dist/
npm-debug.log*
.vscode/
# JetBrains IntelliJ IDEA project files
.idea
*.iml

1
.npmrc Normal file
View File

@@ -0,0 +1 @@
package-lock=true

View File

@@ -1,3 +0,0 @@
language: node_js
node_js:
- lts/*

View File

@@ -39,13 +39,45 @@
- Nuno Campos (nuno.campos@me.com)
- Ebrahim Byagowi (ebrahim@gnu.org)
- Josip Janzic (josip@jjanzic.com)
- Egor Yurtaev (yurtaev.egor@gmail.com)
- Emil Bay (github@tixz.dk)
- Borewit (borewit@users.noreply.github.com)
- greenkeeper[bot] (greenkeeper[bot]@users.noreply.github.com)
- Auyer (rafa_auyer@icloud.com)
- Jon Koops (jonkoops@gmail.com)
- Michael George Attard (michaelgeorgeattard@gmail.com)
- SimplyAhmazing (ahmad19526@gmail.com)
- Cezar Carneiro (cezargcarneiro@gmail.com)
- Bilal Elmoussaoui (bil.elmoussaoui@gmail.com)
- Terry Hau (terryhau@gmail.com)
- Vítor Galvão (info@vitorgalvao.com)
- Borewit (Borewit@users.noreply.github.com)
- Diego Rodríguez (diegorbaquero@gmail.com)
- Dan Flettre (flettre@gmail.com)
- Sibiraj (dev.sibiraj@outlook.com)
- clujin (clujin@gmail.com)
- Sharon Grossman (sharong1337@gmail.com)
- Linus Unnebäck (linus@folkdatorn.se)
- Adrian Tombu (adrian@otso.fr)
- Lucas (5874806+RecoX@users.noreply.github.com)
- David Ernst (dsernst@users.noreply.github.com)
- David Ernst (git@dsernst.com)
- Jimmy Wärting (jimmy@warting.se)
- Recox (5874806+RecoX@users.noreply.github.com)
- greenkeeper[bot] (23040076+greenkeeper[bot]@users.noreply.github.com)
- hicom150 (hicom150@gmail.com)
- Дамјан Георгиевски (gdamjan@gmail.com)
- Jimmy Wärting (jimmy@warting.se)
- Julen Garcia Leunda (hicom150@gmail.com)
- Feross (feross@feross.org)
- Daniele Debernardi (drebrez@gmail.com)
- Chandan Chowdary Bhagam (chandandharana@gmail.com)
- Pieter Goetschalckx (3.14.e.ter@gmail.com)
- Carey Metcalfe (carey@cmetcalfe.ca)
- Ameet Kaustav (akaustav@users.noreply.github.com)
- gpatarin (gael.patarin@outlook.com)
- Gael Patarin (gael.patarin@outlook.com)
- Subin Siby (mail@subinsb.com)
- Hinara (hinara.turevel@gmail.com)
#### Generated by bin/update-authors.sh.

View File

@@ -1,5 +1,92 @@
# WebTorrent Desktop Version History
## v0.24.0 - 2020-08-28
### Added
- Support the `.m2ts` video container format ([hicom150](https://github.com/hicom150))
### Changed
- Update to Electron 10.1.0 [\#1864](https://github.com/webtorrent/webtorrent-desktop/pull/1864) ([feross](https://github.com/feross))
- Update the Windows installer loading image [\#1841](https://github.com/webtorrent/webtorrent-desktop/pull/1841) ([alxhotel](https://github.com/alxhotel))
### Fixed
- Fix music metadata not showing up [\#1847](https://github.com/webtorrent/webtorrent-desktop/pull/1847) ([Borewit](https://github.com/Borewit))
- Fix the "Play in VLC" functionality [\#1850](https://github.com/webtorrent/webtorrent-desktop/pull/1850) ([Hinara](https://github.com/Hinara))
- Prevent shortcuts from activating when user input elements are focused [\#1840](https://github.com/webtorrent/webtorrent-desktop/pull/1840) ([subins2000](https://github.com/subins2000))
## v0.23.0 - 2020-07-15
🔒 This release contains a critical security fix. Please update as soon as possible. [\#1837](https://github.com/webtorrent/webtorrent-desktop/issues/1837#issuecomment-729320901)
### Added
- Add macOS Notarization [\#1834](https://github.com/webtorrent/webtorrent-desktop/pull/1834) ([feross](https://github.com/feross))
### Changed
- Update to Electron 10 beta [\#1834](https://github.com/webtorrent/webtorrent-desktop/pull/1834) ([feross](https://github.com/feross))
## v0.22.0 - 2020-07-15
❤️✨ A new version of WebTorrent Desktop is out! ❤️✨
### Added
- Linux `.rpm` packages and `arm64` builds are now available! [\#1694](https://github.com/webtorrent/webtorrent-desktop/pull/1694) ([hicom150](https://github.com/hicom150))
- Add support for multiple audio tracks [\#1712](https://github.com/webtorrent/webtorrent-desktop/pull/1712) ([hicom150](https://github.com/hicom150))
- Improve codec unsupported detection [\#1711](https://github.com/webtorrent/webtorrent-desktop/pull/1711) ([hicom150](https://github.com/hicom150))
- Report when files are being verified [\#1717](https://github.com/webtorrent/webtorrent-desktop/pull/1717) ([pR0Ps](https://github.com/pR0Ps))
- Support additional audio files: MPEG-Layer-2, Musepack, Matroska audio, WavePack [\#1772](https://github.com/webtorrent/webtorrent-desktop/pull/1772)
### Changed
- Update to Electron 9 [\#1729](https://github.com/webtorrent/webtorrent-desktop/pull/1729) [\#1832](https://github.com/webtorrent/webtorrent-desktop/issues/1832)
- Update to music-metadata 4.8.0 [\#1719](https://github.com/webtorrent/webtorrent-desktop/pull/1719) ([Borewit](https://github.com/Borewit))
- Update Windows build documentation [\#1715](https://github.com/webtorrent/webtorrent-desktop/pull/1715) ([RecoX](https://github.com/RecoX))
- Remove unneeded dependencies ([feross](https://github.com/feross))
### Fixed
- Fix a few type errors [\#1720](https://github.com/webtorrent/webtorrent-desktop/pull/1720) ([mathiasvr](https://github.com/mathiasvr))
- Fix electron SUID sandbox error [\#1707](https://github.com/webtorrent/webtorrent-desktop/pull/1707) ([hicom150](https://github.com/hicom150))
- Fix percentage rounding error [\#1716](https://github.com/webtorrent/webtorrent-desktop/pull/1716) ([pR0Ps](https://github.com/pR0Ps))
- Fix path-selector in preferences page [\#1702](https://github.com/webtorrent/webtorrent-desktop/pull/1702) ([314eter](https://github.com/314eter))
- Fix path-selector in preferences page [\#1704](https://github.com/webtorrent/webtorrent-desktop/pull/1702) ([mathiasvr](https://github.com/mathiasvr))
- Fix: Increase height of 'About' window [\#1737](https://github.com/webtorrent/webtorrent-desktop/pull/1737) ([akaustav](https://github.com/akaustav))
- Fix "Save Torrent File As..." [\#1743](https://github.com/webtorrent/webtorrent-desktop/pull/1743) ([gpatarin](https://github.com/gpatarin))
## v0.21.0 - 2019-09-14
### Added
- Add YouTube style hotkeys [\#1579](https://github.com/webtorrent/webtorrent-desktop/pull/1579) ([dsernst](https://github.com/dsernst))
- Toggle sound notifications on/off [\#1536](https://github.com/webtorrent/webtorrent-desktop/pull/1536) ([adriantombu](https://github.com/adriantombu))
- Ability to play MPEG-4 Audio Book \(.m4b\) [\#1450](https://github.com/webtorrent/webtorrent-desktop/pull/1450) ([Borewit](https://github.com/Borewit))
- Add support for subtitles on Chromecast [\#1165](https://github.com/webtorrent/webtorrent-desktop/pull/1165) ([janza](https://github.com/janza))
### Changed
- Update to Electron 4 [\#1590](https://github.com/webtorrent/webtorrent-desktop/pull/1590) ([Borewit](https://github.com/Borewit))
- Remove '\(BETA\)' from app window title [\#1562](https://github.com/webtorrent/webtorrent-desktop/pull/1562) ([dsernst](https://github.com/dsernst))
- Update React (v16) and Material-UI (v0.20) [\#1483](https://github.com/webtorrent/webtorrent-desktop/pull/1483) ([mathiasvr](https://github.com/mathiasvr))
- Show audio track and disk number [\#1454](https://github.com/webtorrent/webtorrent-desktop/pull/1454) ([Borewit](https://github.com/Borewit))
- Asynchronous music metadata updates while streaming [\#1449](https://github.com/webtorrent/webtorrent-desktop/pull/1449) ([Borewit](https://github.com/Borewit))
- If torrent is not private, leave private flag unset [\#1411](https://github.com/webtorrent/webtorrent-desktop/pull/1411) ([feross](https://github.com/feross))
- Improve audio poster selection: [\#1368](https://github.com/webtorrent/webtorrent-desktop/pull/1368) ([Borewit](https://github.com/Borewit))
- Save preferences immediately when changed [\#1042](https://github.com/webtorrent/webtorrent-desktop/pull/1042) ([Flet](https://github.com/Flet))
### Fixed
- Ensure that the minutes field in playback indicator is zero-padded. [\#1506](https://github.com/webtorrent/webtorrent-desktop/pull/1506) ([bnjmnt4n](https://github.com/bnjmnt4n))
- Bug Fix: Empty Array Reduce [\#1494](https://github.com/webtorrent/webtorrent-desktop/pull/1494) ([clujin](https://github.com/clujin))
- Fix startup problems [\#1419](https://github.com/webtorrent/webtorrent-desktop/pull/1419) ([Borewit](https://github.com/Borewit))
- Add back loading spinner for player page. [\#1311](https://github.com/webtorrent/webtorrent-desktop/pull/1311) ([bnjmnt4n](https://github.com/bnjmnt4n))
- Fix Linux desktop file [\#1309](https://github.com/webtorrent/webtorrent-desktop/pull/1309) ([bilelmoussaoui](https://github.com/bilelmoussaoui))
## v0.20.0 - 2018-04-26
### Added

View File

@@ -1,188 +0,0 @@
# Contributing Guidelines
Contributions welcome!
**Before spending lots of time on something, ask for feedback on your idea first!**
Please search issues and pull requests before adding something new to avoid duplicating
efforts and conversations.
This project welcomes non-code contributions, too! The following types of contributions
are welcome:
- **Ideas**: participate in an issue thread or start your own to have your voice heard.
- **Writing**: contribute your expertise in an area by helping expand the included docs.
- **Copy editing**: fix typos, clarify language, and improve the quality of the docs.
- **Formatting**: help keep docs easy to read with consistent formatting.
## Code Style
[![standard][standard-image]][standard-url]
This repository uses [`standard`][standard-url] to maintain code style and consistency,
and to avoid style arguments. `npm test` runs `standard` automatically, so you don't have
to!
[standard-image]: https://cdn.rawgit.com/feross/standard/master/badge.svg
[standard-url]: https://standardjs.com
## Project Governance
Individuals making significant and valuable contributions are given commit-access to the
project to contribute as they see fit. This project is more like an open wiki than a
standard guarded open source project.
### Rules
There are a few basic ground-rules for contributors:
1. **No `--force` pushes to master** or modifying history in any way. Rebasing and force pushing your own PR branch is fine.
2. **Non-master branches** should be used for ongoing work.
3. **Significant modifications** like API changes should be subject to a **pull request**
to solicit feedback from other contributors.
4. **Pull requests** are *encouraged* for all contributions to solicit feedback, but left to
the discretion of the contributor.
### Releases
Declaring formal releases remains the prerogative of the project maintainer.
### Changes to this arrangement
This is an experiment and feedback is welcome! This document may also be subject to pull-
requests or changes by contributors where you believe you have something valuable to add
or change.
## Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
- (a) The contribution was created in whole or in part by me and I have the right to
submit it under the open source license indicated in the file; or
- (b) The contribution is based upon previous work that, to the best of my knowledge, is
covered under an appropriate open source license and I have the right under that license
to submit that work with modifications, whether created in whole or in part by me, under
the same open source license (unless I am permitted to submit under a different
license), as indicated in the file; or
- (c) The contribution was provided directly to me by some other person who certified
(a), (b) or (c) and I have not modified it.
- (d) I understand and agree that this project and the contribution are public and that a
record of the contribution (including all personal information I submit with it,
including my sign-off) is maintained indefinitely and may be redistributed consistent
with this project or the open source license(s) involved.
## Release Procedure
### 1. Create a new version
- Update `AUTHORS`
```
npm run update-authors
```
Commit if necessary. The commit message should be "authors".
- Write the changelog
You can use `git log --oneline <last version tag>..HEAD` to get a list of changes.
Summarize them concisely in `CHANGELOG.md`. The commit message should be "changelog".
- Update the version
```
npm version [major|minor|patch]
```
This creates both a commit and a git tag.
- Make a PR
Once the PR is reviewed, merge it:
```
git push origin <branch-name>:master
```
This makes it so that the commit hash on master matches the commit hash of the version tag.
Finally, run:
```
git push --tags
```
### 2. Create the release binaries
- On a Mac:
```
npm run package -- darwin --sign
npm run package -- linux --sign
```
- On Windows, or in a Windows VM:
```
npm run package -- win32 --sign
```
- Then, upload the release binaries to Github:
```
npm run gh-release
```
Follow the URL to a newly created Github release page. Manually upload the binaries from
`webtorrent-desktop/dist/`. Open the previous release in another tab, and make sure that you
are uploading the same set of files, no more, no less.
### 3. Test it
**This is the most important part.**
- Manually download the binaries for each platform from Github.
**Do not use your locally built binaries.** Modern OSs treat executables differently if they've
been downloaded, even though the files are byte for byte identical. This ensures that the
codesigning worked and is valid.
- Smoke test WebTorrent Desktop on each platform.
See Smoke Tests below for details. Open DevTools
on Windows and Mac, and ensure that the auto updater is running. If the auto updater does not
run, users will successfully auto update to this new version, and then be stuck there forever.
### 4. Ship it
- Update the website
Create a pull request in [webtorrent.io](https://github.com/webtorrent/webtorrent.io). Update
`config.js`, updating the desktop app version.
As soon as this PR is merged, Jenkins will automatically redeploy the WebTorrent website, and
hundreds of thousands of users around the world will start auto updating. **Merge with care.**
## Smoke Tests
Before a release, check that the following basic use cases work correctly:
1. Click "Play" to stream a built-in torrent (e.g. Sintel)
- Ensure that seeking to undownloaded region works and plays immediately.
- Ensure that sintel.mp4 gets downloaded to `~/Downloads`.
2. Check that the auto-updater works
- Open the console and check for the line "No update available" to indicate
3. Add a new .torrent file via drag-and-drop.
- Ensure that it gets added to the list and starts downloading
4. Remove a torrent from the client
- Ensure that the file is removed from `~/Downloads`
5. Create and seed a new a torrent via drag-and-drop.
- Ensure that the torrent gets created and seeding begins.

View File

@@ -12,8 +12,8 @@
<h4 align="center">The streaming torrent app. For Mac, Windows, and Linux.</h4>
<p align="center">
<a href="https://gitter.im/webtorrent/webtorrent"><img src="https://img.shields.io/badge/gitter-join%20chat%20%E2%86%92-brightgreen.svg" alt="gitter"></a>
<a href="https://travis-ci.org/webtorrent/webtorrent-desktop"><img src="https://img.shields.io/travis/webtorrent/webtorrent-desktop/master.svg" alt="travis"></a>
<a href="https://discord.gg/cnXkm4Z"><img src="https://img.shields.io/discord/612575111718895616" alt="discord"></a>
<a href="https://github.com/webtorrent/webtorrent-desktop/actions/workflows/ci.yml"><img src="https://github.com/webtorrent/webtorrent-desktop/actions/workflows/ci.yml/badge.svg" alt="GitHub CI action"></a>
<a href="https://github.com/webtorrent/webtorrent-desktop/releases"><img src="https://img.shields.io/github/release/webtorrent/webtorrent-desktop.svg" alt="github release version"></a>
<a href="https://github.com/webtorrent/webtorrent-desktop/releases"><img src="https://img.shields.io/github/downloads/webtorrent/webtorrent-desktop/total.svg" alt="github release downloads"></a>
<a href="https://standardjs.com"><img src="https://img.shields.io/badge/code_style-standard-brightgreen.svg" alt="Standard - JavaScript Style Guide"></a>
@@ -35,7 +35,7 @@ Download the latest version of WebTorrent Desktop from
- Use [Homebrew-Cask](https://github.com/caskroom/homebrew-cask) to install from the command line:
```
$ brew cask install webtorrent
$ brew install --cask webtorrent
```
- Try the (unstable) development version by cloning the Git repository. See the
@@ -97,7 +97,7 @@ comparing each one to a reference. Why screenshots?
https://github.com/blog/817-behold-image-view-modes
For MacOS, you'll need a Retina screen for the integration tests to pass. Your screen should have
the same resolution as a 2016 12" Macbook.
the same resolution as a 2018 MacBook Pro 13".
For Windows, you'll need Windows 10 with a 1366x768 screen.
@@ -125,6 +125,7 @@ The following optional arguments are available:
- `--sign` - Sign the application (Mac, Windows)
- `--package=[type]` - Package single output type.
- `deb` - Debian package
- `rpm` - RedHat package
- `zip` - Linux zip file
- `dmg` - Mac disk image
- `exe` - Windows installer
@@ -141,11 +142,12 @@ The Windows app can be packaged from **any** platform.
Note: Windows code signing only works from **Windows**, for now.
Note: To package the Windows app from non-Windows platforms,
[Wine](https://www.winehq.org/) needs to be installed. For example on Mac, first
install [XQuartz](http://www.xquartz.org/), then run:
[Wine](https://www.winehq.org/) and [Mono](https://www.mono-project.com/) need
to be installed. For example on Mac, first install
[XQuartz](http://www.xquartz.org/), then run:
```
brew install wine
$ brew install wine mono
```
(Requires the [Homebrew](http://brew.sh/) package manager.)
@@ -158,6 +160,22 @@ The Mac app can only be packaged from **macOS**.
The Linux app can be packaged from **any** platform.
If packaging from Mac, install system dependencies with Homebrew by running:
```
npm run install-system-deps
```
#### Recommended readings to start working in the app
Electron (Framework to make native apps for Windows, OSX and Linux in Javascript):
https://electronjs.org/docs/tutorial/quick-start
React.js (Framework to work with Frontend UI):
https://reactjs.org/docs/getting-started.html
Material UI (React components that implement Google's Material Design.):
https://material-ui.com/getting-started/installation
### Privacy
WebTorrent Desktop collects some basic usage stats to help us make the app better.

109
RELEASE_PROCESS.md Normal file
View File

@@ -0,0 +1,109 @@
## Release Process
### 1. Create a new version
- Update `AUTHORS`
```
npm run update-authors
```
Commit if necessary. The commit message should be "authors".
- Write the changelog
You can use `git log --oneline <last version tag>..HEAD` to get a list of changes.
Summarize them concisely in `CHANGELOG.md`. The commit message should be "changelog".
- Update the version
```
npm version [major|minor|patch]
```
This creates both a commit and a git tag.
- Make a PR
Once the PR is reviewed, merge it:
```
git push origin <branch-name>:master
```
This makes it so that the commit hash on master matches the commit hash of the version tag.
Finally, run:
```
git push --tags
```
### 2. Create the release binaries
- On a Mac:
```
npm run package -- darwin --sign
```
Move the `.zip` and `.dmg` file somewhere because the next step wipes the `dist/` folder away.
```
npm run package -- linux --sign
```
- On Windows, or in a Windows VM:
```
npm run package -- win32 --sign
```
- Then, upload the release binaries to Github:
```
npm run gh-release
```
Follow the URL to a newly created Github release page. Manually upload the binaries from
`webtorrent-desktop/dist/`. Open the previous release in another tab, and make sure that you
are uploading the same set of files, no more, no less.
### 3. Test it
**This is the most important part.**
- Manually download the binaries for each platform from Github.
**Do not use your locally built binaries.** Modern OSs treat executables differently if they've
been downloaded, even though the files are byte for byte identical. This ensures that the
codesigning worked and is valid.
- Smoke test WebTorrent Desktop on each platform. Before a release, check that the following basic use cases work correctly:
1. Click "Play" to stream a built-in torrent (e.g. Sintel)
- Ensure that seeking to undownloaded region works and plays immediately.
- Ensure that sintel.mp4 gets downloaded to `~/Downloads`.
2. Check that the auto-updater works
- Open the console and check for the line "No update available" to indicate that the auto-updater is working. (If the auto updater does not run, users will successfully auto update to this new version, and then be stuck there forever.)
3. Add a new .torrent file via drag-and-drop.
- Ensure that it gets added to the list and starts downloading.
4. Remove a torrent from the client
- Ensure that the file is removed from `~/Downloads`
5. Create and seed a new a torrent via drag-and-drop.
- Ensure that the torrent gets created and seeding begins.
### 4. Ship it
- Update the website
Create a pull request in [webtorrent.io](https://github.com/webtorrent/webtorrent.io). Update
`config.js`, updating the desktop app version.
Once this PR is merged and Feross redeploys the WebTorrent website,
hundreds of thousands of users around the world will start auto updating. **Merge with care.**

View File

@@ -1,43 +0,0 @@
# Security Policies and Procedures
This document outlines security procedures and general policies for the WebTorrent
project.
* [Reporting a Bug](#reporting-a-bug)
* [Disclosure Policy](#disclosure-policy)
* [Comments on this Policy](#comments-on-this-policy)
## Reporting a Bug
The WebTorrent team and community take all security bugs in WebTorrent seriously.
Thank you for improving the security of WebTorrent. We appreciate your efforts and
responsible disclosure and will make every effort to acknowledge your
contributions.
Report security bugs by emailing the lead maintainer at feross@feross.org.
The lead maintainer will acknowledge your email within 48 hours, and will send a
more detailed response within 48 hours indicating the next steps in handling
your report. After the initial reply to your report, the security team will
endeavor to 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).
## Disclosure Policy
When the security team receives a security bug report, they will assign it to a
primary handler. This person will coordinate the fix and release process,
involving the following steps:
* Confirm the problem and determine the affected versions.
* Audit code to find any potential similar problems.
* Prepare fixes for all releases still under maintenance. These fixes will be
released as fast as possible to npm.
## Comments on this Policy
If you have suggestions on how this process could be improved please submit a
pull request.

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.debugger</key>
<true/>
</dict>
</plist>

View File

@@ -1,46 +0,0 @@
#!/usr/bin/env node
const walkSync = require('walk-sync')
const fs = require('fs')
const path = require('path')
let hasErrors = false
// Find all Javascript source files
const files = walkSync('src', { globs: ['**/*.js'] })
console.log('Running extra-lint on ' + files.length + ' files...')
// Read each file, line by line
files.forEach(function (file) {
const filepath = path.join('src', file)
const lines = fs.readFileSync(filepath, 'utf8').split('\n')
lines.forEach(function (line, i) {
let error
// Consistent JSX tag closing
if (line.match(/' {2}\/> *$/) ||
line.match('[^ ]/> *$') ||
line.match(' > *$')) {
error = 'JSX tag spacing'
}
// No lines over 100 characters
if (line.length > 100) {
error = 'Line >100 chars'
}
if (line.match(/^var /) || line.match(/ var /)) {
error = 'Use const or let'
}
if (error) {
let name = path.basename(file)
console.log('%s:%d - %s:\n%s', name, i + 1, error, line)
hasErrors = true
}
})
})
if (hasErrors) process.exit(1)
else console.log('Looks good!')

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env node
const { CONFIG_PATH } = require('../src/config')
const opn = require('opn')
const open = require('open')
opn(CONFIG_PATH)
open(CONFIG_PATH)

View File

@@ -8,7 +8,6 @@ const cp = require('child_process')
const electronPackager = require('electron-packager')
const fs = require('fs')
const minimist = require('minimist')
const mkdirp = require('mkdirp')
const os = require('os')
const path = require('path')
const rimraf = require('rimraf')
@@ -37,10 +36,9 @@ const argv = minimist(process.argv.slice(2), {
})
function build () {
console.log('Reinstalling node_modules...')
console.log('Installing node_modules...')
rimraf.sync(NODE_MODULES_PATH)
cp.execSync('npm install', { stdio: 'inherit' })
cp.execSync('npm dedupe', { stdio: 'inherit' })
cp.execSync('npm ci', { stdio: 'inherit' })
console.log('Nuking dist/ and build/...')
rimraf.sync(DIST_PATH)
@@ -71,11 +69,11 @@ function build () {
const all = {
// The human-readable copyright line for the app. Maps to the `LegalCopyright` metadata
// property on Windows, and `NSHumanReadableCopyright` on Mac.
'app-copyright': config.APP_COPYRIGHT,
appCopyright: config.APP_COPYRIGHT,
// The release version of the application. Maps to the `ProductVersion` metadata
// property on Windows, and `CFBundleShortVersionString` on Mac.
'app-version': pkg.version,
appVersion: pkg.version,
// Package the application's source code into an archive, using Electron's archive
// format. Mitigates issues around long path names on Windows and slightly speeds up
@@ -89,7 +87,7 @@ const all = {
// The build version of the application. Maps to the FileVersion metadata property on
// Windows, and CFBundleVersion on Mac. Note: Windows requires the build version to
// start with a number. We're using the version of the underlying WebTorrent library.
'build-version': require('webtorrent/package.json').version,
buildVersion: require('webtorrent/package.json').version,
// The application source directory.
dir: config.ROOT_PATH,
@@ -119,18 +117,18 @@ const darwin = {
// Build for Mac
platform: 'darwin',
// Build x64 binaries only.
// Build x64 binary only.
arch: 'x64',
// The bundle identifier to use in the application's plist (Mac only).
'app-bundle-id': 'io.webtorrent.webtorrent',
appBundleId: 'io.webtorrent.webtorrent',
// The application category type, as shown in the Finder via "View" -> "Arrange by
// Application Category" when viewing the Applications directory (Mac only).
'app-category-type': 'public.app-category.utilities',
appCategoryType: 'public.app-category.utilities',
// The bundle identifier to use in the application helper's plist (Mac only).
'helper-bundle-id': 'io.webtorrent.webtorrent-helper',
helperBundleId: 'io.webtorrent.webtorrent-helper',
// Application icon.
icon: config.APP_ICON + '.icns'
@@ -140,8 +138,8 @@ const win32 = {
// Build for Windows.
platform: 'win32',
// Build ia32 and x64 binaries.
arch: ['ia32', 'x64'],
// Build x64 binary only.
arch: 'x64',
// Object hash of application metadata to embed into the executable (Windows only)
win32metadata: {
@@ -174,8 +172,8 @@ const linux = {
// Build for Linux.
platform: 'linux',
// Build ia32 and x64 binaries.
arch: ['ia32', 'x64']
// Build x64, armv7l, and arm64 binaries.
arch: ['x64', 'armv7l', 'arm64']
// Note: Application icon for Linux is specified via the BrowserWindow `icon` option.
}
@@ -186,8 +184,7 @@ function buildDarwin (cb) {
const plist = require('plist')
console.log('Mac: Packaging electron...')
electronPackager(Object.assign({}, all, darwin), function (err, buildPath) {
if (err) return cb(err)
electronPackager(Object.assign({}, all, darwin)).then(function (buildPath) {
console.log('Mac: Packaged electron. ' + buildPath)
const appPath = path.join(buildPath[0], config.APP_NAME + '.app')
@@ -198,16 +195,16 @@ function buildDarwin (cb) {
infoPlist.CFBundleDocumentTypes = [
{
CFBundleTypeExtensions: [ 'torrent' ],
CFBundleTypeExtensions: ['torrent'],
CFBundleTypeIconFile: path.basename(config.APP_FILE_ICON) + '.icns',
CFBundleTypeName: 'BitTorrent Document',
CFBundleTypeRole: 'Editor',
LSHandlerRank: 'Owner',
LSItemContentTypes: [ 'org.bittorrent.torrent' ]
LSItemContentTypes: ['org.bittorrent.torrent']
},
{
CFBundleTypeName: 'Any',
CFBundleTypeOSTypes: [ '****' ],
CFBundleTypeOSTypes: ['****'],
CFBundleTypeRole: 'Editor',
LSHandlerRank: 'Owner',
LSTypeIsPackage: false
@@ -219,13 +216,13 @@ function buildDarwin (cb) {
CFBundleTypeRole: 'Editor',
CFBundleURLIconFile: path.basename(config.APP_FILE_ICON) + '.icns',
CFBundleURLName: 'BitTorrent Magnet URL',
CFBundleURLSchemes: [ 'magnet' ]
CFBundleURLSchemes: ['magnet']
},
{
CFBundleTypeRole: 'Editor',
CFBundleURLIconFile: path.basename(config.APP_FILE_ICON) + '.icns',
CFBundleURLName: 'BitTorrent Stream-Magnet URL',
CFBundleURLSchemes: [ 'stream-magnet' ]
CFBundleURLSchemes: ['stream-magnet']
}
]
@@ -242,7 +239,7 @@ function buildDarwin (cb) {
UTTypeReferenceURL: 'http://www.bittorrent.org/beps/bep_0000.html',
UTTypeTagSpecification: {
'com.apple.ostype': 'TORR',
'public.filename-extension': [ 'torrent' ],
'public.filename-extension': ['torrent'],
'public.mime-type': 'application/x-bittorrent'
}
}
@@ -269,6 +266,7 @@ function buildDarwin (cb) {
function signApp (cb) {
const sign = require('electron-osx-sign')
const { notarize } = require('electron-notarize')
/*
* Sign the app with Apple Developer ID certificates. We sign the app for 2 reasons:
@@ -284,16 +282,37 @@ function buildDarwin (cb) {
* - Membership in the Apple Developer Program
*/
const signOpts = {
verbose: true,
app: appPath,
platform: 'darwin',
verbose: true
identity: 'Developer ID Application: WebTorrent, LLC (5MAMC8G3L8)',
hardenedRuntime: true,
entitlements: path.join(config.ROOT_PATH, 'bin', 'darwin-entitlements.plist'),
'entitlements-inherit': path.join(config.ROOT_PATH, 'bin', 'darwin-entitlements.plist'),
'signature-flags': 'library'
}
const notarizeOpts = {
appBundleId: darwin.appBundleId,
appPath,
appleId: 'feross@feross.org',
appleIdPassword: '@keychain:AC_PASSWORD'
}
console.log('Mac: Signing app...')
sign(signOpts, function (err) {
if (err) return cb(err)
console.log('Mac: Signed app.')
cb(null)
console.log('Mac: Notarizing app...')
notarize(notarizeOpts).then(
function () {
console.log('Mac: Notarized app.')
cb(null)
},
function (err) {
cb(err)
})
})
}
@@ -356,6 +375,8 @@ function buildDarwin (cb) {
cb(null)
})
}
}).catch(function (err) {
cb(err)
})
}
@@ -376,8 +397,7 @@ function buildWin32 (cb) {
CERT_PATH = path.join(os.homedir(), 'Desktop')
}
electronPackager(Object.assign({}, all, win32), function (err, buildPath) {
if (err) return cb(err)
electronPackager(Object.assign({}, all, win32)).then(function (buildPath) {
console.log('Windows: Packaged electron. ' + buildPath)
let signWithParams
@@ -396,21 +416,17 @@ function buildWin32 (cb) {
const tasks = []
buildPath.forEach(function (filesPath) {
const destArch = filesPath.split('-').pop()
if (argv.package === 'exe' || argv.package === 'all') {
tasks.push((cb) => packageInstaller(filesPath, destArch, cb))
tasks.push((cb) => packageInstaller(filesPath, cb))
}
if (argv.package === 'portable' || argv.package === 'all') {
tasks.push((cb) => packagePortable(filesPath, destArch, cb))
tasks.push((cb) => packagePortable(filesPath, cb))
}
})
series(tasks, cb)
function packageInstaller (filesPath, destArch, cb) {
console.log(`Windows: Creating ${destArch} installer...`)
const archStr = destArch === 'ia32' ? '-ia32' : ''
function packageInstaller (filesPath, cb) {
console.log('Windows: Creating installer...')
installer.createWindowsInstaller({
appDirectory: filesPath,
@@ -423,34 +439,25 @@ function buildWin32 (cb) {
noMsi: true,
outputDirectory: DIST_PATH,
productName: config.APP_NAME,
/**
* Only create delta updates for the Windows x64 build because 90% of our
* users have Windows x64 and the delta files take a *very* long time to
* generate. Also, the ia32 files on GitHub have non-standard Squirrel
* names (i.e. RELEASES-ia32 instead of RELEASES) and so Squirrel won't
* find them unless we proxy the requests.
*/
// TODO: Re-enable Windows 64-bit delta updates when we confirm that they
// work correctly in the presence of the "ia32" .nupkg files. I
// (feross) noticed them listed in the 64-bit RELEASES file and
// manually edited them out for the v0.17 release. Shipping only
// full updates for now will work fine, with no ill-effects.
// remoteReleases: destArch === 'x64'
// ? config.GITHUB_URL
// : undefined,
// remoteReleases: config.GITHUB_URL,
/**
* If you hit a "GitHub API rate limit exceeded" error, set this token!
*/
// remoteToken: process.env.WEBTORRENT_GITHUB_API_TOKEN,
setupExe: config.APP_NAME + 'Setup-v' + config.APP_VERSION + archStr + '.exe',
setupExe: config.APP_NAME + 'Setup-v' + config.APP_VERSION + '.exe',
setupIcon: config.APP_ICON + '.ico',
signWithParams: signWithParams,
signWithParams,
title: config.APP_NAME,
usePackageJson: false,
version: pkg.version
})
.then(function () {
console.log(`Windows: Created ${destArch} installer.`)
console.log('Windows: Created installer.')
/**
* Delete extraneous Squirrel files (i.e. *.nupkg delta files for older
@@ -462,68 +469,39 @@ function buildWin32 (cb) {
fs.unlinkSync(path.join(DIST_PATH, filename))
})
if (destArch === 'ia32') {
console.log('Windows: Renaming ia32 installer files...')
// RELEASES -> RELEASES-ia32
const relPath = path.join(DIST_PATH, 'RELEASES-ia32')
fs.renameSync(
path.join(DIST_PATH, 'RELEASES'),
relPath
)
// WebTorrent-vX.X.X-full.nupkg -> WebTorrent-vX.X.X-ia32-full.nupkg
fs.renameSync(
path.join(DIST_PATH, `${config.APP_NAME}-${config.APP_VERSION}-full.nupkg`),
path.join(DIST_PATH, `${config.APP_NAME}-${config.APP_VERSION}-ia32-full.nupkg`)
)
// Change file name inside RELEASES-ia32 to match renamed file
const relContent = fs.readFileSync(relPath, 'utf8')
const relContent32 = relContent.replace('full.nupkg', 'ia32-full.nupkg')
fs.writeFileSync(relPath, relContent32)
if (relContent === relContent32) {
// Sanity check
throw new Error('Fixing RELEASES-ia32 failed. Replacement did not modify the file.')
}
console.log('Windows: Renamed ia32 installer files.')
}
cb(null)
})
.catch(cb)
}
function packagePortable (filesPath, destArch, cb) {
console.log(`Windows: Creating ${destArch} portable app...`)
function packagePortable (filesPath, cb) {
console.log('Windows: Creating portable app...')
const portablePath = path.join(filesPath, 'Portable Settings')
mkdirp.sync(portablePath)
fs.mkdirSync(portablePath, { recursive: true })
const downloadsPath = path.join(portablePath, 'Downloads')
mkdirp.sync(downloadsPath)
fs.mkdirSync(downloadsPath, { recursive: true })
const tempPath = path.join(portablePath, 'Temp')
mkdirp.sync(tempPath)
const archStr = destArch === 'ia32' ? '-ia32' : ''
fs.mkdirSync(tempPath, { recursive: true })
const inPath = path.join(DIST_PATH, path.basename(filesPath))
const outPath = path.join(DIST_PATH, BUILD_NAME + '-win' + archStr + '.zip')
const outPath = path.join(DIST_PATH, BUILD_NAME + '-win.zip')
zip.zipSync(inPath, outPath)
console.log(`Windows: Created ${destArch} portable app.`)
console.log('Windows: Created portable app.')
cb(null)
}
}).catch(function (err) {
cb(err)
})
}
function buildLinux (cb) {
console.log('Linux: Packaging electron...')
electronPackager(Object.assign({}, all, linux), function (err, buildPath) {
if (err) return cb(err)
electronPackager(Object.assign({}, all, linux)).then(function (buildPath) {
console.log('Linux: Packaged electron. ' + buildPath)
const tasks = []
@@ -533,56 +511,102 @@ function buildLinux (cb) {
if (argv.package === 'deb' || argv.package === 'all') {
tasks.push((cb) => packageDeb(filesPath, destArch, cb))
}
if (argv.package === 'rpm' || argv.package === 'all') {
tasks.push((cb) => packageRpm(filesPath, destArch, cb))
}
if (argv.package === 'zip' || argv.package === 'all') {
tasks.push((cb) => packageZip(filesPath, destArch, cb))
}
})
series(tasks, cb)
}).catch(function (err) {
cb(err)
})
function packageDeb (filesPath, destArch, cb) {
// Linux convention for Debian based 'x64' is 'amd64'
if (destArch === 'x64') {
destArch = 'amd64'
}
// Create .deb file for Debian-based platforms
console.log(`Linux: Creating ${destArch} deb...`)
const deb = require('nobin-debian-installer')()
const destPath = path.join('/opt', pkg.name)
const installer = require('electron-installer-debian')
deb.pack({
package: pkg,
info: {
arch: destArch === 'x64' ? 'amd64' : 'i386',
targetDir: DIST_PATH,
depends: 'gconf2, libgtk2.0-0, libnss3, libxss1',
scripts: {
postinst: path.join(config.STATIC_PATH, 'linux', 'postinst'),
prerm: path.join(config.STATIC_PATH, 'linux', 'prerm')
}
}
}, [{
src: ['./**'],
dest: destPath,
expand: true,
cwd: filesPath
}, {
src: ['./**'],
dest: path.join('/usr', 'share'),
expand: true,
cwd: path.join(config.STATIC_PATH, 'linux', 'share')
}], function (err) {
if (err) return cb(err)
console.log(`Linux: Created ${destArch} deb.`)
cb(null)
})
const options = {
src: filesPath + '/',
dest: DIST_PATH,
arch: destArch,
bin: 'WebTorrent',
icon: {
'48x48': path.join(config.STATIC_PATH, 'linux/share/icons/hicolor/48x48/apps/webtorrent-desktop.png'),
'256x256': path.join(config.STATIC_PATH, 'linux/share/icons/hicolor/256x256/apps/webtorrent-desktop.png')
},
categories: ['Network', 'FileTransfer', 'P2P'],
mimeType: ['application/x-bittorrent', 'x-scheme-handler/magnet', 'x-scheme-handler/stream-magnet'],
desktopTemplate: path.join(config.STATIC_PATH, 'linux/webtorrent-desktop.ejs'),
lintianOverrides: [
'unstripped-binary-or-object',
'embedded-library',
'missing-dependency-on-libc',
'changelog-file-missing-in-native-package',
'description-synopsis-is-duplicated',
'setuid-binary',
'binary-without-manpage',
'shlib-with-executable-bit'
]
}
installer(options).then(
() => {
console.log(`Linux: Created ${destArch} deb.`)
cb(null)
},
(err) => cb(err)
)
}
function packageRpm (filesPath, destArch, cb) {
// Linux convention for RedHat based 'x64' is 'x86_64'
if (destArch === 'x64') {
destArch = 'x86_64'
}
// Create .rpm file for RedHat-based platforms
console.log(`Linux: Creating ${destArch} rpm...`)
const installer = require('electron-installer-redhat')
const options = {
src: filesPath + '/',
dest: DIST_PATH,
arch: destArch,
bin: 'WebTorrent',
icon: {
'48x48': path.join(config.STATIC_PATH, 'linux/share/icons/hicolor/48x48/apps/webtorrent-desktop.png'),
'256x256': path.join(config.STATIC_PATH, 'linux/share/icons/hicolor/256x256/apps/webtorrent-desktop.png')
},
categories: ['Network', 'FileTransfer', 'P2P'],
mimeType: ['application/x-bittorrent', 'x-scheme-handler/magnet', 'x-scheme-handler/stream-magnet'],
desktopTemplate: path.join(config.STATIC_PATH, 'linux/webtorrent-desktop.ejs')
}
installer(options).then(
() => {
console.log(`Linux: Created ${destArch} rpm.`)
cb(null)
},
(err) => cb(err)
)
}
function packageZip (filesPath, destArch, cb) {
// Create .zip file for Linux
console.log(`Linux: Creating ${destArch} zip...`)
const archStr = destArch === 'ia32' ? '-ia32' : ''
const inPath = path.join(DIST_PATH, path.basename(filesPath))
const outPath = path.join(DIST_PATH, BUILD_NAME + '-linux' + archStr + '.zip')
const outPath = path.join(DIST_PATH, `${BUILD_NAME}-linux-${destArch}.zip`)
zip.zipSync(inPath, outPath)
console.log(`Linux: Created ${destArch} zip.`)

View File

@@ -13,6 +13,7 @@ while (<>) {
next if /(dc\@DCs-MacBook.local)/;
next if /(rolandoguedes\@gmail.com)/;
next if /(grunjol\@users.noreply.github.com)/;
next if /(dependabot)/;
$seen{$_} = push @authors, "- ", $_;
}
END {

32580
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,79 +1,88 @@
{
"name": "webtorrent-desktop",
"description": "WebTorrent, the streaming torrent client. For Mac, Windows, and Linux.",
"version": "0.20.0",
"version": "0.24.0",
"author": {
"name": "WebTorrent, LLC",
"email": "feross@webtorrent.io",
"url": "https://webtorrent.io"
},
"babel": {
"plugins": [
[
"@babel/plugin-transform-react-jsx",
{
"useBuiltIns": true
}
]
]
},
"bugs": {
"url": "https://github.com/webtorrent/webtorrent-desktop/issues"
},
"dependencies": {
"airplayer": "^2.0.0",
"application-config": "^1.0.0",
"arch": "^2.0.0",
"auto-launch": "^4.0.1",
"bitfield": "^1.0.2",
"capture-frame": "^2.0.0",
"chokidar": "^2.0.4",
"chromecasts": "^1.9.1",
"cp-file": "^6.0.0",
"create-torrent": "^3.24.5",
"debounce": "^1.0.0",
"deep-equal": "^1.0.1",
"dlnacasts": "^0.1.0",
"drag-drop": "^4.1.0",
"es6-error": "^4.0.0",
"fn-getter": "^1.0.0",
"iso-639-1": "^1.2.1",
"languagedetect": "^1.1.1",
"location-history": "^1.0.0",
"material-ui": "^0.17.0",
"mkdirp": "^0.5.1",
"music-metadata": "^3.1.0",
"network-address": "^1.1.0",
"parse-torrent": "^6.0.1",
"prettier-bytes": "^1.0.1",
"react": "^15.4.2",
"react-dom": "^15.4.2",
"react-tap-event-plugin": "^2.0.1",
"rimraf": "^2.5.2",
"run-parallel": "^1.1.6",
"semver": "^5.1.0",
"simple-concat": "^1.0.0",
"simple-get": "^3.0.3",
"srt-to-vtt": "^1.1.1",
"vlc-command": "^1.0.1",
"webtorrent": "0.x",
"winreg": "^1.2.0",
"zero-fill": "^2.2.3"
"@electron/remote": "2.1.3",
"airplayer": "github:webtorrent/airplayer#fix-security",
"application-config": "2.0.0",
"arch": "2.2.0",
"auto-launch": "5.0.5",
"bitfield": "4.1.0",
"capture-frame": "4.0.0",
"chokidar": "3.5.3",
"chromecasts": "1.10.2",
"create-torrent": "5.0.9",
"debounce": "1.2.1",
"dlnacasts": "0.1.0",
"drag-drop": "7.2.0",
"es6-error": "4.1.1",
"fn-getter": "1.0.0",
"iso-639-1": "2.1.15",
"languagedetect": "2.0.0",
"location-history": "1.1.2",
"material-ui": "0.20.2",
"music-metadata": "7.14.0",
"network-address": "1.1.2",
"parse-torrent": "9.1.5",
"prettier-bytes": "1.0.4",
"prop-types": "15.8.1",
"react": "17.0.2",
"react-dom": "17.0.2",
"rimraf": "4.4.0",
"run-parallel": "1.2.0",
"semver": "7.3.8",
"simple-concat": "1.0.1",
"simple-get": "4.0.1",
"srt-to-vtt": "1.1.3",
"vlc-command": "1.2.0",
"webtorrent": "1.9.7",
"winreg": "1.2.4"
},
"devDependencies": {
"babel-eslint": "^9.0.0",
"buble": "^0.19.3",
"cross-zip": "^2.0.1",
"depcheck": "^0.6.4",
"electron": "1.6.16",
"electron-osx-sign": "^0.4.10",
"electron-packager": "~8.5.1",
"electron-winstaller": "^2.6.4",
"gh-release": "^3.2.1",
"minimist": "^1.2.0",
"nobin-debian-installer": "0.0.10",
"nodemon": "^1.10.2",
"opn": "^5.4.0",
"plist": "^3.0.1",
"pngjs": "^3.0.0",
"run-series": "^1.1.4",
"spectron": "^3.3.0",
"standard": "*",
"tape": "^4.6.0",
"walk-sync": "^0.3.1"
"@babel/cli": "7.28.6",
"@babel/core": "7.29.0",
"@babel/eslint-parser": "7.28.6",
"@babel/plugin-transform-react-jsx": "7.28.6",
"cross-zip": "4.0.0",
"depcheck": "1.4.7",
"electron": "27.3.11",
"electron-notarize": "1.2.2",
"electron-osx-sign": "0.6.0",
"electron-packager": "17.1.2",
"electron-winstaller": "5.4.0",
"gh-release": "7.0.2",
"minimist": "1.2.8",
"nodemon": "2.0.22",
"open": "8.4.2",
"plist": "3.1.0",
"pngjs": "7.0.0",
"run-series": "1.1.9",
"spectron": "19.0.0",
"standard": "17.0.0",
"tape": "5.9.0"
},
"engines": {
"node": ">=4.0.0"
"node": "^16.0.0 || ^18.0.0",
"npm": "^7.10.0 || ^8.0.0 || ^9.0.0 || ^10.0.0"
},
"homepage": "https://webtorrent.io",
"keywords": [
@@ -89,7 +98,9 @@
"license": "MIT",
"main": "index.js",
"optionalDependencies": {
"appdmg": "^0.4.3"
"appdmg": "^0.6.0",
"electron-installer-debian": "^3.2.0",
"electron-installer-redhat": "^3.4.0"
},
"private": true,
"productName": "WebTorrent",
@@ -98,19 +109,24 @@
"url": "git://github.com/webtorrent/webtorrent-desktop.git"
},
"scripts": {
"build": "buble src --output build",
"build": "babel src --out-dir build",
"clean": "node ./bin/clean.js",
"gh-release": "gh-release",
"install-system-deps": "brew install fakeroot dpkg rpm",
"open-config": "node ./bin/open-config.js",
"package": "node ./bin/package.js",
"prepublish": "npm run build",
"start": "npm run build && electron .",
"test": "standard && depcheck --ignores=standard,babel-eslint --ignore-dirs=build,dist && node ./bin/extra-lint.js",
"start": "npm run build && electron --no-sandbox .",
"test": "standard && depcheck --ignores=standard,@babel/eslint-parser --ignore-dirs=build,dist",
"test-integration": "npm run build && node ./test",
"update-authors": "./bin/update-authors.sh",
"watch": "nodemon --exec \"npm run start\" --ext js,css --ignore build/ --ignore dist/"
},
"standard": {
"parser": "babel-eslint"
"parser": "@babel/eslint-parser"
},
"renovate": {
"extends": [
"github>webtorrent/renovate-config"
]
}
}

View File

@@ -1,6 +1,6 @@
const appConfig = require('application-config')('WebTorrent')
const path = require('path')
const electron = require('electron')
const { app } = require('electron')
const arch = require('arch')
const APP_NAME = 'WebTorrent'
@@ -23,13 +23,13 @@ module.exports = {
CRASH_REPORT_URL: 'https://webtorrent.io/desktop/crash-report',
TELEMETRY_URL: 'https://webtorrent.io/desktop/telemetry',
APP_COPYRIGHT: 'Copyright © 2014-2018 ' + APP_TEAM,
APP_COPYRIGHT: `Copyright © 2014-${new Date().getFullYear()} ${APP_TEAM}`,
APP_FILE_ICON: path.join(__dirname, '..', 'static', 'WebTorrentFile'),
APP_ICON: path.join(__dirname, '..', 'static', 'WebTorrent'),
APP_NAME: APP_NAME,
APP_TEAM: APP_TEAM,
APP_VERSION: APP_VERSION,
APP_WINDOW_TITLE: APP_NAME + ' (BETA)',
APP_NAME,
APP_TEAM,
APP_VERSION,
APP_WINDOW_TITLE: APP_NAME,
CONFIG_PATH: getConfigPath(),
@@ -73,12 +73,14 @@ module.exports = {
GITHUB_URL: 'https://github.com/webtorrent/webtorrent-desktop',
GITHUB_URL_ISSUES: 'https://github.com/webtorrent/webtorrent-desktop/issues',
GITHUB_URL_RAW: 'https://raw.githubusercontent.com/webtorrent/webtorrent-desktop/master',
GITHUB_URL_RELEASES: 'https://github.com/webtorrent/webtorrent-desktop/releases',
HOME_PAGE_URL: 'https://webtorrent.io',
TWITTER_PAGE_URL: 'https://twitter.com/WebTorrentApp',
IS_PORTABLE: IS_PORTABLE,
IS_PRODUCTION: IS_PRODUCTION,
IS_TEST: IS_TEST,
IS_PORTABLE,
IS_PRODUCTION,
IS_TEST,
OS_SYSARCH: arch() === 'x64' ? 'x64' : 'ia32',
@@ -98,8 +100,8 @@ module.exports = {
WINDOW_MIN_HEIGHT: UI_HEADER_HEIGHT + (UI_TORRENT_HEIGHT * 2), // header + 2 torrents
WINDOW_MIN_WIDTH: 425,
UI_HEADER_HEIGHT: UI_HEADER_HEIGHT,
UI_TORRENT_HEIGHT: UI_TORRENT_HEIGHT
UI_HEADER_HEIGHT,
UI_TORRENT_HEIGHT
}
function getConfigPath () {
@@ -124,10 +126,10 @@ function getPath (key) {
return ''
} else if (process.type === 'renderer') {
// Electron renderer process
return electron.remote.app.getPath(key)
return require('@electron/remote').app.getPath(key)
} else {
// Electron main process
return electron.app.getPath(key)
return app.getPath(key)
}
}

View File

@@ -4,11 +4,12 @@ module.exports = {
function init () {
const config = require('./config')
const electron = require('electron')
const { crashReporter } = require('electron')
electron.crashReporter.start({
companyName: config.APP_NAME,
crashReporter.start({
productName: config.APP_NAME,
submitURL: config.CRASH_REPORT_URL
submitURL: config.CRASH_REPORT_URL,
globalExtra: { _companyName: config.APP_NAME },
compress: true
})
}

View File

@@ -2,7 +2,7 @@ module.exports = {
init
}
const electron = require('electron')
const { dialog } = require('electron')
const config = require('../config')
const log = require('./log')
@@ -44,13 +44,11 @@ function onResponse (err, res, data) {
}
}
electron.dialog.showMessageBox({
dialog.showMessageBox({
type: 'info',
buttons: ['OK'],
title: data.title,
message: data.message,
detail: data.detail
}, noop)
})
}
function noop () {}

View File

@@ -6,7 +6,7 @@ module.exports = {
openFiles
}
const electron = require('electron')
const { dialog } = require('electron')
const log = require('./log')
const windows = require('./windows')
@@ -19,7 +19,7 @@ function openSeedFile () {
log('openSeedFile')
const opts = {
title: 'Select a file for the torrent.',
properties: [ 'openFile' ]
properties: ['openFile']
}
showOpenSeed(opts)
}
@@ -34,13 +34,13 @@ function openSeedDirectory () {
log('openSeedDirectory')
const opts = process.platform === 'darwin'
? {
title: 'Select a file or folder for the torrent.',
properties: [ 'openFile', 'openDirectory' ]
}
title: 'Select a file or folder for the torrent.',
properties: ['openFile', 'openDirectory']
}
: {
title: 'Select a folder for the torrent.',
properties: [ 'openDirectory' ]
}
title: 'Select a folder for the torrent.',
properties: ['openDirectory']
}
showOpenSeed(opts)
}
@@ -53,19 +53,18 @@ function openFiles () {
log('openFiles')
const opts = process.platform === 'darwin'
? {
title: 'Select a file or folder to add.',
properties: [ 'openFile', 'openDirectory' ]
}
title: 'Select a file or folder to add.',
properties: ['openFile', 'openDirectory']
}
: {
title: 'Select a file to add.',
properties: [ 'openFile' ]
}
title: 'Select a file to add.',
properties: ['openFile']
}
setTitle(opts.title)
electron.dialog.showOpenDialog(windows.main.win, opts, function (selectedPaths) {
resetTitle()
if (!Array.isArray(selectedPaths)) return
windows.main.dispatch('onOpen', selectedPaths)
})
const selectedPaths = dialog.showOpenDialogSync(windows.main.win, opts)
resetTitle()
if (!Array.isArray(selectedPaths)) return
windows.main.dispatch('onOpen', selectedPaths)
}
/*
@@ -77,15 +76,14 @@ function openTorrentFile () {
const opts = {
title: 'Select a .torrent file.',
filters: [{ name: 'Torrent Files', extensions: ['torrent'] }],
properties: [ 'openFile', 'multiSelections' ]
properties: ['openFile', 'multiSelections']
}
setTitle(opts.title)
electron.dialog.showOpenDialog(windows.main.win, opts, function (selectedPaths) {
resetTitle()
if (!Array.isArray(selectedPaths)) return
selectedPaths.forEach(function (selectedPath) {
windows.main.dispatch('addTorrent', selectedPath)
})
const selectedPaths = dialog.showOpenDialogSync(windows.main.win, opts)
resetTitle()
if (!Array.isArray(selectedPaths)) return
selectedPaths.forEach(selectedPath => {
windows.main.dispatch('addTorrent', selectedPath)
})
}
@@ -116,9 +114,8 @@ function resetTitle () {
*/
function showOpenSeed (opts) {
setTitle(opts.title)
electron.dialog.showOpenDialog(windows.main.win, opts, function (selectedPaths) {
resetTitle()
if (!Array.isArray(selectedPaths)) return
windows.main.dispatch('showCreateTorrent', selectedPaths)
})
const selectedPaths = dialog.showOpenDialogSync(windows.main.win, opts)
resetTitle()
if (!Array.isArray(selectedPaths)) return
windows.main.dispatch('showCreateTorrent', selectedPaths)
}

View File

@@ -34,7 +34,7 @@ function setBadge (count) {
if (process.platform === 'darwin' ||
(process.platform === 'linux' && app.isUnityRunning())) {
log(`setBadge: ${count}`)
app.setBadgeCount(Number(count))
app.badgeCount = Number(count)
}
}

View File

@@ -17,12 +17,12 @@ let proc = null
function checkInstall (playerPath, cb) {
// check for VLC if external player has not been specified by the user
// otherwise assume the player is installed
if (playerPath == null) return vlcCommand(cb)
if (!playerPath) return vlcCommand(cb)
process.nextTick(() => cb(null))
}
function spawn (playerPath, url, title) {
if (playerPath != null) return spawnExternal(playerPath, [url])
if (playerPath) return spawnExternal(playerPath, [url])
// Try to find and use VLC if external player is not specified
vlcCommand((err, vlcPath) => {

View File

@@ -12,8 +12,6 @@ function install () {
break
case 'win32': installWin32()
break
case 'linux': installLinux()
break
}
}
@@ -23,14 +21,11 @@ function uninstall () {
break
case 'win32': uninstallWin32()
break
case 'linux': uninstallLinux()
break
}
}
function installDarwin () {
const electron = require('electron')
const app = electron.app
const { app } = require('electron')
// On Mac, only protocols that are listed in `Info.plist` can be set as the
// default handler at runtime.
@@ -42,7 +37,7 @@ function installDarwin () {
function uninstallDarwin () {}
const EXEC_COMMAND = [ process.execPath, '--' ]
const EXEC_COMMAND = [process.execPath, '--']
if (!config.IS_PRODUCTION) {
EXEC_COMMAND.push(config.ROOT_PATH)
@@ -269,100 +264,3 @@ function uninstallWin32 () {
function commandToArgs (command) {
return command.map((arg) => `"${arg}"`).join(' ')
}
function installLinux () {
const fs = require('fs')
const os = require('os')
const path = require('path')
const config = require('../config')
const log = require('./log')
// Do not install in user dir if running on system
if (/^\/opt/.test(process.execPath)) return
installDesktopFile()
installIconFile()
function installDesktopFile () {
const templatePath = path.join(
config.STATIC_PATH, 'linux', 'webtorrent-desktop.desktop'
)
fs.readFile(templatePath, 'utf8', writeDesktopFile)
}
function writeDesktopFile (err, desktopFile) {
if (err) return log.error(err.message)
const appPath = config.IS_PRODUCTION
? path.dirname(process.execPath)
: config.ROOT_PATH
desktopFile = desktopFile
.replace(/\$APP_NAME/g, config.APP_NAME)
.replace(/\$APP_PATH/g, appPath)
.replace(/\$EXEC_PATH/g, EXEC_COMMAND.join(' '))
.replace(/\$TRY_EXEC_PATH/g, process.execPath)
const desktopFilePath = path.join(
os.homedir(),
'.local',
'share',
'applications',
'webtorrent-desktop.desktop'
)
fs.mkdirp(path.dirname(desktopFilePath))
fs.writeFile(desktopFilePath, desktopFile, err => {
if (err) return log.error(err.message)
})
}
function installIconFile () {
const iconStaticPath = path.join(config.STATIC_PATH, 'WebTorrent.png')
fs.readFile(iconStaticPath, writeIconFile)
}
function writeIconFile (err, iconFile) {
if (err) return log.error(err.message)
const mkdirp = require('mkdirp')
const iconFilePath = path.join(
os.homedir(),
'.local',
'share',
'icons',
'webtorrent-desktop.png'
)
mkdirp(path.dirname(iconFilePath), err => {
if (err) return log.error(err.message)
fs.writeFile(iconFilePath, iconFile, err => {
if (err) log.error(err.message)
})
})
}
}
function uninstallLinux () {
const os = require('os')
const path = require('path')
const rimraf = require('rimraf')
const desktopFilePath = path.join(
os.homedir(),
'.local',
'share',
'applications',
'webtorrent-desktop.desktop'
)
rimraf(desktopFilePath)
const iconFilePath = path.join(
os.homedir(),
'.local',
'share',
'icons',
'webtorrent-desktop.png'
)
rimraf(iconFilePath)
}

View File

@@ -1,21 +1,29 @@
console.time('init')
const electron = require('electron')
const app = electron.app
require('@electron/remote/main').initialize()
const { app, ipcMain } = require('electron')
// Start crash reporter early, so it takes effect for child processes
const crashReporter = require('../crash-reporter')
crashReporter.init()
const parallel = require('run-parallel')
const config = require('../config')
const crashReporter = require('../crash-reporter')
const ipc = require('./ipc')
const log = require('./log')
const menu = require('./menu')
const State = require('../renderer/lib/state')
const windows = require('./windows')
const WEBTORRENT_VERSION = require('webtorrent/package.json').version
let shouldQuit = false
let argv = sliceArgv(process.argv)
// allow electron/chromium to play startup sounds (without user interaction)
app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required')
// Start the app without showing the main window when auto launching on login
// (On Windows and Linux, we get a flag. On MacOS, we get special API.)
const hidden = argv.includes('--hidden') ||
@@ -38,17 +46,19 @@ if (!shouldQuit && !config.IS_PORTABLE) {
// signal this instance and quit. Note: This feature creates a lock file in
// %APPDATA%\Roaming\WebTorrent so we do not do it for the Portable App since
// we want to be "silent" as well as "portable".
shouldQuit = app.makeSingleInstance(onAppOpen)
if (shouldQuit) {
app.quit()
if (!app.requestSingleInstanceLock()) {
shouldQuit = true
}
}
if (!shouldQuit) {
if (shouldQuit) {
app.quit()
} else {
init()
}
function init () {
app.on('second-instance', (event, commandLine, workingDirectory) => onAppOpen(commandLine))
if (config.IS_PORTABLE) {
const path = require('path')
// Put all user data into the "Portable Settings" folder
@@ -57,8 +67,6 @@ function init () {
app.setPath('temp', path.join(config.CONFIG_PATH, 'Temp'))
}
const ipcMain = electron.ipcMain
let isReady = false // app ready, windows can be created
app.ipcReady = false // main window has finished loading and IPC is ready
app.isQuitting = false
@@ -74,9 +82,9 @@ function init () {
isReady = true
const state = results.state
windows.main.init(state, { hidden: hidden })
windows.webtorrent.init()
menu.init()
windows.main.init(state, { hidden })
windows.webtorrent.init()
// To keep app startup fast, some code is delayed.
setTimeout(() => {
@@ -91,22 +99,24 @@ function init () {
})
}
// Enable app logging into default directory, i.e. /Library/Logs/WebTorrent
// on Mac, %APPDATA% on Windows, $XDG_CONFIG_HOME or ~/.config on Linux.
app.setAppLogsPath()
app.userAgentFallback = `WebTorrent/${WEBTORRENT_VERSION} (https://webtorrent.io)`
app.on('open-file', onOpen)
app.on('open-url', onOpen)
ipc.init()
app.once('will-finish-launching', function () {
crashReporter.init()
})
app.once('ipcReady', function () {
app.once('ipcReady', () => {
log('Command line args:', argv)
processArgv(argv)
console.timeEnd('init')
})
app.on('before-quit', function (e) {
app.on('before-quit', e => {
if (app.isQuitting) return
app.isQuitting = true
@@ -119,7 +129,7 @@ function init () {
}, 4000) // quit after 4 secs, at most
})
app.on('activate', function () {
app.on('activate', () => {
if (isReady) windows.main.show()
})
}
@@ -162,7 +172,7 @@ function onOpen (e, torrentId) {
// Electron issue: https://github.com/atom/electron/issues/4338
setTimeout(() => windows.main.show(), 100)
processArgv([ torrentId ])
processArgv([torrentId])
} else {
argv.push(torrentId)
}
@@ -186,14 +196,18 @@ function onAppOpen (newArgv) {
// Development: 2 args, eg: electron .
// Test: 4 args, eg: electron -r .../mocks.js .
function sliceArgv (argv) {
return argv.slice(config.IS_PRODUCTION ? 1
: config.IS_TEST ? 4
: 2)
return argv.slice(
config.IS_PRODUCTION
? 1
: config.IS_TEST
? 4
: 2
)
}
function processArgv (argv) {
let torrentIds = []
argv.forEach(function (arg) {
const torrentIds = []
argv.forEach(arg => {
if (arg === '-n' || arg === '-o' || arg === '-u') {
// Critical path: Only load the 'dialog' package if it is needed
const dialog = require('./dialog')

View File

@@ -3,9 +3,7 @@ module.exports = {
setModule
}
const electron = require('electron')
const app = electron.app
const { app, ipcMain } = require('electron')
const log = require('./log')
const menu = require('./menu')
@@ -23,18 +21,16 @@ function setModule (name, module) {
}
function init () {
const ipc = electron.ipcMain
ipc.once('ipcReady', function (e) {
ipcMain.once('ipcReady', e => {
app.ipcReady = true
app.emit('ipcReady')
})
ipc.once('ipcReadyWebTorrent', function (e) {
ipcMain.once('ipcReadyWebTorrent', e => {
app.ipcReadyWebTorrent = true
log('sending %d queued messages from the main win to the webtorrent window',
messageQueueMainToWebTorrent.length)
messageQueueMainToWebTorrent.forEach(function (message) {
messageQueueMainToWebTorrent.forEach(message => {
windows.webtorrent.send(message.name, ...message.args)
log('webtorrent: sent queued %s', message.name)
})
@@ -44,11 +40,11 @@ function init () {
* Dialog
*/
ipc.on('openTorrentFile', () => {
ipcMain.on('openTorrentFile', () => {
const dialog = require('./dialog')
dialog.openTorrentFile()
})
ipc.on('openFiles', () => {
ipcMain.on('openFiles', () => {
const dialog = require('./dialog')
dialog.openFiles()
})
@@ -57,11 +53,11 @@ function init () {
* Dock
*/
ipc.on('setBadge', (e, ...args) => {
ipcMain.on('setBadge', (e, ...args) => {
const dock = require('./dock')
dock.setBadge(...args)
})
ipc.on('downloadFinished', (e, ...args) => {
ipcMain.on('downloadFinished', (e, ...args) => {
const dock = require('./dock')
dock.downloadFinished(...args)
})
@@ -70,7 +66,7 @@ function init () {
* Player Events
*/
ipc.on('onPlayerOpen', function () {
ipcMain.on('onPlayerOpen', () => {
const powerSaveBlocker = require('./power-save-blocker')
const shortcuts = require('./shortcuts')
const thumbar = require('./thumbar')
@@ -81,14 +77,14 @@ function init () {
thumbar.enable()
})
ipc.on('onPlayerUpdate', function (e, ...args) {
ipcMain.on('onPlayerUpdate', (e, ...args) => {
const thumbar = require('./thumbar')
menu.onPlayerUpdate(...args)
thumbar.onPlayerUpdate(...args)
})
ipc.on('onPlayerClose', function () {
ipcMain.on('onPlayerClose', () => {
const powerSaveBlocker = require('./power-save-blocker')
const shortcuts = require('./shortcuts')
const thumbar = require('./thumbar')
@@ -99,7 +95,7 @@ function init () {
thumbar.disable()
})
ipc.on('onPlayerPlay', function () {
ipcMain.on('onPlayerPlay', () => {
const powerSaveBlocker = require('./power-save-blocker')
const thumbar = require('./thumbar')
@@ -107,7 +103,7 @@ function init () {
thumbar.onPlayerPlay()
})
ipc.on('onPlayerPause', function () {
ipcMain.on('onPlayerPause', () => {
const powerSaveBlocker = require('./power-save-blocker')
const thumbar = require('./thumbar')
@@ -119,37 +115,37 @@ function init () {
* Folder Watcher Events
*/
ipc.on('startFolderWatcher', function () {
if (!modules['folderWatcher']) {
ipcMain.on('startFolderWatcher', () => {
if (!modules.folderWatcher) {
log('IPC ERR: folderWatcher module is not defined.')
return
}
modules['folderWatcher'].start()
modules.folderWatcher.start()
})
ipc.on('stopFolderWatcher', function () {
if (!modules['folderWatcher']) {
ipcMain.on('stopFolderWatcher', () => {
if (!modules.folderWatcher) {
log('IPC ERR: folderWatcher module is not defined.')
return
}
modules['folderWatcher'].stop()
modules.folderWatcher.stop()
})
/**
* Shell
*/
ipc.on('openItem', (e, ...args) => {
ipcMain.on('openPath', (e, ...args) => {
const shell = require('./shell')
shell.openItem(...args)
shell.openPath(...args)
})
ipc.on('showItemInFolder', (e, ...args) => {
ipcMain.on('showItemInFolder', (e, ...args) => {
const shell = require('./shell')
shell.showItemInFolder(...args)
})
ipc.on('moveItemToTrash', (e, ...args) => {
ipcMain.on('moveItemToTrash', (e, ...args) => {
const shell = require('./shell')
shell.moveItemToTrash(...args)
})
@@ -158,7 +154,7 @@ function init () {
* File handlers
*/
ipc.on('setDefaultFileHandler', (e, flag) => {
ipcMain.on('setDefaultFileHandler', (e, flag) => {
const handlers = require('./handlers')
if (flag) handlers.install()
@@ -169,7 +165,7 @@ function init () {
* Auto start on login
*/
ipc.on('setStartup', (e, flag) => {
ipcMain.on('setStartup', (e, flag) => {
const startup = require('./startup')
if (flag) startup.install()
@@ -182,36 +178,38 @@ function init () {
const main = windows.main
ipc.on('setAspectRatio', (e, ...args) => main.setAspectRatio(...args))
ipc.on('setBounds', (e, ...args) => main.setBounds(...args))
ipc.on('setProgress', (e, ...args) => main.setProgress(...args))
ipc.on('setTitle', (e, ...args) => main.setTitle(...args))
ipc.on('show', () => main.show())
ipc.on('toggleFullScreen', (e, ...args) => main.toggleFullScreen(...args))
ipc.on('setAllowNav', (e, ...args) => menu.setAllowNav(...args))
ipcMain.on('setAspectRatio', (e, ...args) => main.setAspectRatio(...args))
ipcMain.on('setBounds', (e, ...args) => main.setBounds(...args))
ipcMain.on('setProgress', (e, ...args) => main.setProgress(...args))
ipcMain.on('setTitle', (e, ...args) => main.setTitle(...args))
ipcMain.on('show', () => main.show())
ipcMain.on('toggleFullScreen', (e, ...args) => main.toggleFullScreen(...args))
ipcMain.on('setAllowNav', (e, ...args) => menu.setAllowNav(...args))
/**
* External Media Player
*/
ipc.on('checkForExternalPlayer', function (e, path) {
ipcMain.on('checkForExternalPlayer', (e, path) => {
const externalPlayer = require('./external-player')
externalPlayer.checkInstall(path, function (err) {
externalPlayer.checkInstall(path, err => {
windows.main.send('checkForExternalPlayer', !err)
})
})
ipc.on('openExternalPlayer', (e, ...args) => {
ipcMain.on('openExternalPlayer', (e, ...args) => {
const externalPlayer = require('./external-player')
const shortcuts = require('./shortcuts')
const thumbar = require('./thumbar')
menu.togglePlaybackControls(false)
shortcuts.disable()
thumbar.disable()
externalPlayer.spawn(...args)
})
ipc.on('quitExternalPlayer', () => {
ipcMain.on('quitExternalPlayer', () => {
const externalPlayer = require('./external-player')
externalPlayer.kill()
})
@@ -220,11 +218,12 @@ function init () {
* Message passing
*/
const oldEmit = ipc.emit
ipc.emit = function (name, e, ...args) {
const oldEmit = ipcMain.emit
ipcMain.emit = (name, e, ...args) => {
// Relay messages between the main window and the WebTorrent hidden window
if (name.startsWith('wt-') && !app.isQuitting) {
if (e.sender.browserWindowOptions.title === 'webtorrent-hidden-window') {
console.dir(e.sender.getTitle())
if (e.sender.getTitle() === 'WebTorrent Hidden Window') {
// Send message to main window
windows.main.send(name, ...args)
log('webtorrent: got %s', name)
@@ -235,8 +234,8 @@ function init () {
} else {
// Queue message for webtorrent window, it hasn't finished loading yet
messageQueueMainToWebTorrent.push({
name: name,
args: args
name,
args
})
log('webtorrent: queueing %s', name)
}
@@ -244,6 +243,6 @@ function init () {
}
// Emit all other events normally
oldEmit.call(ipc, name, e, ...args)
oldEmit.call(ipcMain, name, e, ...args)
}
}

View File

@@ -8,11 +8,9 @@ module.exports.error = error
* where they can be viewed in Developer Tools.
*/
const electron = require('electron')
const { app } = require('electron')
const windows = require('./windows')
const app = electron.app
function log (...args) {
if (app.ipcReady) {
windows.main.send('log', ...args)

View File

@@ -8,9 +8,7 @@ module.exports = {
onToggleFullScreen
}
const electron = require('electron')
const app = electron.app
const { app, Menu } = require('electron')
const config = require('../config')
const windows = require('./windows')
@@ -18,8 +16,8 @@ const windows = require('./windows')
let menu = null
function init () {
menu = electron.Menu.buildFromTemplate(getMenuTemplate())
electron.Menu.setApplicationMenu(menu)
menu = Menu.buildFromTemplate(getMenuTemplate())
Menu.setApplicationMenu(menu)
}
function togglePlaybackControls (flag) {
@@ -70,12 +68,11 @@ function onToggleFullScreen (flag) {
}
function getMenuItem (label) {
for (let i = 0; i < menu.items.length; i++) {
const menuItem = menu.items[i].submenu.items.find(function (item) {
return item.label === label
})
if (menuItem) return menuItem
for (const menuItem of menu.items) {
const submenuItem = menuItem.submenu.items.find(item => item.label === label)
if (submenuItem) return submenuItem
}
return {}
}
function getMenuTemplate () {
@@ -288,6 +285,14 @@ function getMenuTemplate () {
{
label: 'Resume All',
click: () => windows.main.dispatch('resumeAllTorrents')
},
{
label: 'Remove All From List',
click: () => windows.main.dispatch('confirmDeleteAllTorrents', false)
},
{
label: 'Remove All Data Files',
click: () => windows.main.dispatch('confirmDeleteAllTorrents', true)
}
]
},
@@ -302,6 +307,13 @@ function getMenuTemplate () {
shell.openExternal(config.HOME_PAGE_URL)
}
},
{
label: 'Release Notes',
click: () => {
const shell = require('./shell')
shell.openExternal(config.GITHUB_URL_RELEASES)
}
},
{
label: 'Contribute on GitHub',
click: () => {
@@ -318,6 +330,13 @@ function getMenuTemplate () {
const shell = require('./shell')
shell.openExternal(config.GITHUB_URL_ISSUES)
}
},
{
label: 'Follow us on Twitter',
click: () => {
const shell = require('./shell')
shell.openExternal(config.TWITTER_PAGE_URL)
}
}
]
}
@@ -343,8 +362,7 @@ function getMenuTemplate () {
type: 'separator'
},
{
role: 'services',
submenu: []
role: 'services'
},
{
type: 'separator'

View File

@@ -3,7 +3,7 @@ module.exports = {
disable
}
const electron = require('electron')
const { powerSaveBlocker } = require('electron')
const log = require('./log')
let blockId = 0
@@ -13,11 +13,11 @@ let blockId = 0
* display.
*/
function enable () {
if (electron.powerSaveBlocker.isStarted(blockId)) {
if (powerSaveBlocker.isStarted(blockId)) {
// If a power saver block already exists, do nothing.
return
}
blockId = electron.powerSaveBlocker.start('prevent-display-sleep')
blockId = powerSaveBlocker.start('prevent-display-sleep')
log(`powerSaveBlocker.enable: ${blockId}`)
}
@@ -25,10 +25,10 @@ function enable () {
* Stop blocking the system from entering low-power mode.
*/
function disable () {
if (!electron.powerSaveBlocker.isStarted(blockId)) {
if (!powerSaveBlocker.isStarted(blockId)) {
// If a power saver block does not exist, do nothing.
return
}
electron.powerSaveBlocker.stop(blockId)
powerSaveBlocker.stop(blockId)
log(`powerSaveBlocker.disable: ${blockId}`)
}

View File

@@ -1,11 +1,11 @@
module.exports = {
openExternal,
openItem,
openPath,
showItemInFolder,
moveItemToTrash
}
const electron = require('electron')
const { shell } = require('electron')
const log = require('./log')
/**
@@ -13,15 +13,16 @@ const log = require('./log')
*/
function openExternal (url) {
log(`openExternal: ${url}`)
electron.shell.openExternal(url)
shell.openExternal(url)
}
/**
* Open the given file in the desktops default manner.
*/
function openItem (path) {
log(`openItem: ${path}`)
electron.shell.openItem(path)
function openPath (path) {
log(`openPath: ${path}`)
shell.openPath(path)
}
/**
@@ -29,7 +30,7 @@ function openItem (path) {
*/
function showItemInFolder (path) {
log(`showItemInFolder: ${path}`)
electron.shell.showItemInFolder(path)
shell.showItemInFolder(path)
}
/**
@@ -37,5 +38,5 @@ function showItemInFolder (path) {
*/
function moveItemToTrash (path) {
log(`moveItemToTrash: ${path}`)
electron.shell.moveItemToTrash(path)
shell.trashItem(path)
}

View File

@@ -3,20 +3,20 @@ module.exports = {
enable
}
const electron = require('electron')
const { globalShortcut } = require('electron')
const windows = require('./windows')
function enable () {
// Register play/pause media key, available on some keyboards.
electron.globalShortcut.register(
globalShortcut.register(
'MediaPlayPause',
() => windows.main.dispatch('playPause')
)
electron.globalShortcut.register(
globalShortcut.register(
'MediaNextTrack',
() => windows.main.dispatch('nextTrack')
)
electron.globalShortcut.register(
globalShortcut.register(
'MediaPreviousTrack',
() => windows.main.dispatch('previousTrack')
)
@@ -24,7 +24,7 @@ function enable () {
function disable () {
// Return the media key to the OS, so other apps can use it.
electron.globalShortcut.unregister('MediaPlayPause')
electron.globalShortcut.unregister('MediaNextTrack')
electron.globalShortcut.unregister('MediaPreviousTrack')
globalShortcut.unregister('MediaPlayPause')
globalShortcut.unregister('MediaNextTrack')
globalShortcut.unregister('MediaPreviousTrack')
}

View File

@@ -2,150 +2,39 @@ module.exports = {
handleEvent
}
const cp = require('child_process')
const electron = require('electron')
const fs = require('fs')
const os = require('os')
const path = require('path')
const { app } = require('electron')
const app = electron.app
const path = require('path')
const spawn = require('child_process').spawn
const handlers = require('./handlers')
const EXE_NAME = path.basename(process.execPath)
const UPDATE_EXE = path.join(process.execPath, '..', '..', 'Update.exe')
function handleEvent (cmd) {
if (cmd === '--squirrel-install') {
// App was installed. Install desktop/start menu shortcuts.
createShortcuts(function () {
// Ensure user sees install splash screen so they realize that Setup.exe actually
// installed an application and isn't the application itself.
setTimeout(function () {
app.quit()
}, 3000)
})
return true
}
const run = (args, done) => {
spawn(UPDATE_EXE, args, { detached: true })
.on('close', done)
}
if (cmd === '--squirrel-updated') {
// App was updated. (Called on new version of app)
updateShortcuts(function () {
app.quit()
})
function handleEvent (cmd) {
if (cmd === '--squirrel-install' || cmd === '--squirrel-updated') {
run([`--createShortcut=${EXE_NAME}`], app.quit)
return true
}
if (cmd === '--squirrel-uninstall') {
// App was just uninstalled. Undo anything we did in the --squirrel-install and
// --squirrel-updated handlers
// Uninstall .torrent file and magnet link handlers
handlers.uninstall()
// Remove desktop/start menu shortcuts.
// HACK: add a callback to handlers.uninstall() so we can remove this setTimeout
setTimeout(function () {
removeShortcuts(function () {
app.quit()
})
}, 1000)
run([`--removeShortcut=${EXE_NAME}`], app.quit)
return true
}
if (cmd === '--squirrel-obsolete') {
// App will be updated. (Called on outgoing version of app)
app.quit()
return true
}
if (cmd === '--squirrel-firstrun') {
// App is running for the first time. Do not quit, allow startup to continue.
return false
}
return false
}
/**
* Spawn a command and invoke the callback when it completes with an error and
* the output from standard out.
*/
function spawn (command, args, cb) {
let stdout = ''
let error = null
let child = null
try {
child = cp.spawn(command, args)
} catch (err) {
// Spawn can throw an error
process.nextTick(function () {
cb(error, stdout)
})
return
}
child.stdout.on('data', function (data) {
stdout += data
})
child.on('error', function (processError) {
error = processError
})
child.on('close', function (code, signal) {
if (code !== 0 && !error) error = new Error('Command failed: #{signal || code}')
if (error) error.stdout = stdout
cb(error, stdout)
})
}
/**
* Spawn the Squirrel `Update.exe` command with the given arguments and invoke
* the callback when the command completes.
*/
function spawnUpdate (args, cb) {
spawn(UPDATE_EXE, args, cb)
}
/**
* Create desktop and start menu shortcuts using the Squirrel `Update.exe`
* command.
*/
function createShortcuts (cb) {
spawnUpdate(['--createShortcut', EXE_NAME], cb)
}
/**
* Update desktop and start menu shortcuts using the Squirrel `Update.exe`
* command.
*/
function updateShortcuts (cb) {
const homeDir = os.homedir()
if (homeDir) {
const desktopShortcutPath = path.join(homeDir, 'Desktop', 'WebTorrent.lnk')
// If the desktop shortcut was deleted by the user, then keep it deleted.
fs.access(desktopShortcutPath, function (err) {
const desktopShortcutExists = !err
createShortcuts(function () {
if (desktopShortcutExists) {
cb()
} else {
// Remove the unwanted desktop shortcut that was recreated
fs.unlink(desktopShortcutPath, cb)
}
})
})
} else {
createShortcuts(cb)
}
}
/**
* Remove desktop and start menu shortcuts using the Squirrel `Update.exe`
* command.
*/
function removeShortcuts (cb) {
spawnUpdate(['--removeShortcut', EXE_NAME], cb)
}

View File

@@ -3,19 +3,11 @@ module.exports = {
uninstall
}
const config = require('../config')
const { APP_NAME } = require('../config')
const AutoLaunch = require('auto-launch')
const { app } = require('electron')
// On Mac, work around a bug in auto-launch where it opens a Terminal window
// See https://github.com/Teamwork/node-auto-launch/issues/28#issuecomment-222194437
const appPath = process.platform === 'darwin'
? app.getPath('exe').replace(/\.app\/Content.*/, '.app')
: undefined // Use the default
const appLauncher = new AutoLaunch({
name: config.APP_NAME,
path: appPath,
name: APP_NAME,
isHidden: true
})

View File

@@ -77,8 +77,8 @@ function onPlayerPlay () {
function onPlayerUpdate (state) {
if (!isEnabled()) return
buttons[PREV].flags = [ state.hasPrevious ? 'enabled' : 'disabled' ]
buttons[NEXT].flags = [ state.hasNext ? 'enabled' : 'disabled' ]
buttons[PREV].flags = [state.hasPrevious ? 'enabled' : 'disabled']
buttons[NEXT].flags = [state.hasNext ? 'enabled' : 'disabled']
update()
}

View File

@@ -4,9 +4,7 @@ module.exports = {
setWindowFocus
}
const electron = require('electron')
const app = electron.app
const { app, Tray, Menu } = require('electron')
const config = require('../config')
const windows = require('./windows')
@@ -36,7 +34,7 @@ function setWindowFocus (flag) {
}
function initLinux () {
checkLinuxTraySupport(function (err) {
checkLinuxTraySupport(err => {
if (!err) createTray()
})
}
@@ -46,28 +44,20 @@ function initWin32 () {
}
/**
* Check for libappindicator1 support before creating tray icon
* Check for libappindicator support before creating tray icon.
*/
function checkLinuxTraySupport (cb) {
const cp = require('child_process')
// Check that we're on Ubuntu (or another debian system) and that we have
// libappindicator1. If WebTorrent was installed from the deb file, we should
// always have it. If it was installed from the zip file, we might not.
cp.exec('dpkg --get-selections libappindicator1', function (err, stdout) {
// Check that libappindicator libraries are installed in system.
cp.exec('ldconfig -p | grep libappindicator', (err, stdout) => {
if (err) return cb(err)
// Unfortunately there's no cleaner way, as far as I can tell, to check
// whether a debian package is installed:
if (stdout.endsWith('\tinstall\n')) {
cb(null)
} else {
cb(new Error('debian package not installed'))
}
cb(null)
})
}
function createTray () {
tray = new electron.Tray(getIconPath())
tray = new Tray(getIconPath())
// On Windows, left click opens the app, right click opens the context menu.
// On Linux, any click (left or right) opens the context menu.
@@ -78,7 +68,7 @@ function createTray () {
}
function updateTrayMenu () {
const contextMenu = electron.Menu.buildFromTemplate(getMenuTemplate())
const contextMenu = Menu.buildFromTemplate(getMenuTemplate())
tray.setContextMenu(contextMenu)
}

View File

@@ -2,7 +2,7 @@ module.exports = {
init
}
const electron = require('electron')
const { autoUpdater } = require('electron')
const get = require('simple-get')
const config = require('../config')
@@ -47,31 +47,31 @@ function onResponse (err, res, data) {
}
function initDarwinWin32 () {
electron.autoUpdater.on(
autoUpdater.on(
'error',
(err) => log.error(`Update error: ${err.message}`)
)
electron.autoUpdater.on(
autoUpdater.on(
'checking-for-update',
() => log('Checking for update')
)
electron.autoUpdater.on(
autoUpdater.on(
'update-available',
() => log('Update available')
)
electron.autoUpdater.on(
autoUpdater.on(
'update-not-available',
() => log('No update available')
)
electron.autoUpdater.on(
autoUpdater.on(
'update-downloaded',
(e, notes, name, date, url) => log(`Update downloaded: ${name}: ${url}`)
)
electron.autoUpdater.setFeedURL(AUTO_UPDATE_URL)
electron.autoUpdater.checkForUpdates()
autoUpdater.setFeedURL({ url: AUTO_UPDATE_URL })
autoUpdater.checkForUpdates()
}

View File

@@ -2,9 +2,7 @@ module.exports = {
init
}
const electron = require('electron')
const app = electron.app
const { app } = require('electron')
/**
* Add a user task menu to the app icon on right-click. (Windows)

View File

@@ -4,18 +4,18 @@ const about = module.exports = {
}
const config = require('../../config')
const electron = require('electron')
const { BrowserWindow } = require('electron')
function init () {
if (about.win) {
return about.win.show()
}
const win = about.win = new electron.BrowserWindow({
const win = about.win = new BrowserWindow({
backgroundColor: '#ECECEC',
center: true,
fullscreen: false,
height: 170,
height: 250,
icon: getIconPath(),
maximizable: false,
minimizable: false,
@@ -24,19 +24,28 @@ function init () {
skipTaskbar: true,
title: 'About ' + config.APP_WINDOW_TITLE,
useContentSize: true,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
enableBlinkFeatures: 'AudioVideoTracks',
enableRemoteModule: true,
backgroundThrottling: false
},
width: 300
})
require('@electron/remote/main').enable(win.webContents)
win.loadURL(config.WINDOW_ABOUT)
// No menu on the About window
win.setMenu(null)
win.once('ready-to-show', function () {
win.once('ready-to-show', () => {
win.show()
// No menu on the About window
// Hack: BrowserWindow removeMenu method not working on electron@7
// https://github.com/electron/electron/issues/21088
win.setMenuBarVisibility(false)
})
win.once('closed', function () {
win.once('closed', () => {
about.win = null
})
}

View File

@@ -14,11 +14,9 @@ const main = module.exports = {
win: null
}
const electron = require('electron')
const { app, BrowserWindow, screen } = require('electron')
const debounce = require('debounce')
const app = electron.app
const config = require('../../config')
const log = require('../log')
const menu = require('../menu')
@@ -30,9 +28,8 @@ function init (state, options) {
const initialBounds = Object.assign(config.WINDOW_INITIAL_BOUNDS, state.saved.bounds)
const win = main.win = new electron.BrowserWindow({
const win = main.win = new BrowserWindow({
backgroundColor: '#282828',
backgroundThrottling: false, // do not throttle animations/timers when page is background
darkTheme: true, // Forces dark theme (GTK+3)
height: initialBounds.height,
icon: getIconPath(), // Window icon (Windows, Linux)
@@ -40,12 +37,20 @@ function init (state, options) {
minWidth: config.WINDOW_MIN_WIDTH,
show: false,
title: config.APP_WINDOW_TITLE,
titleBarStyle: 'hidden-inset', // Hide title bar (Mac)
titleBarStyle: 'hiddenInset', // Hide title bar (Mac)
useContentSize: true, // Specify web page size without OS chrome
width: initialBounds.width,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
enableBlinkFeatures: 'AudioVideoTracks',
enableRemoteModule: true,
backgroundThrottling: false
},
x: initialBounds.x,
y: initialBounds.y
})
require('@electron/remote/main').enable(win.webContents)
win.loadURL(config.WINDOW_MAIN)
@@ -61,7 +66,7 @@ function init (state, options) {
menu.onToggleFullScreen(main.win.isFullScreen())
})
win.webContents.on('will-navigate', (e, url) => {
win.webContents.on('will-navigate', (e) => {
// Prevent drag-and-drop from navigating the Electron window, which can happen
// before our drag-and-drop handlers have been initialized.
e.preventDefault()
@@ -86,11 +91,11 @@ function init (state, options) {
})
win.on('move', debounce(e => {
send('windowBoundsChanged', e.sender.getBounds())
send('windowBoundsChanged', main.win.getBounds())
}, 1000))
win.on('resize', debounce(e => {
send('windowBoundsChanged', e.sender.getBounds())
send('windowBoundsChanged', main.win.getBounds())
}, 1000))
win.on('close', e => {
@@ -138,7 +143,7 @@ function setAspectRatio (aspectRatio) {
function setBounds (bounds, maximize) {
// Do nothing in fullscreen
if (!main.win || main.win.isFullScreen()) {
log(`setBounds: not setting bounds because we're in full screen`)
log('setBounds: not setting bounds because already in full screen mode')
return
}
@@ -147,7 +152,7 @@ function setBounds (bounds, maximize) {
log('setBounds: maximizing')
main.win.maximize()
} else if (maximize === false && main.win.isMaximized()) {
log('setBounds: unmaximizing')
log('setBounds: minimizing')
main.win.unmaximize()
}
@@ -157,7 +162,7 @@ function setBounds (bounds, maximize) {
log(`setBounds: setting bounds to ${JSON.stringify(bounds)}`)
if (bounds.x === null && bounds.y === null) {
// X and Y not specified? By default, center on current screen
const scr = electron.screen.getDisplayMatching(main.win.getBounds())
const scr = screen.getDisplayMatching(main.win.getBounds())
bounds.x = Math.round(scr.bounds.x + (scr.bounds.width / 2) - (bounds.width / 2))
bounds.y = Math.round(scr.bounds.y + (scr.bounds.height / 2) - (bounds.height / 2))
log(`setBounds: centered to ${JSON.stringify(bounds)}`)
@@ -209,7 +214,7 @@ function toggleDevTools () {
if (main.win.webContents.isDevToolsOpened()) {
main.win.webContents.closeDevTools()
} else {
main.win.webContents.openDevTools({ detach: true })
main.win.webContents.openDevTools({ mode: 'detach' })
}
}

View File

@@ -6,14 +6,13 @@ const webtorrent = module.exports = {
win: null
}
const electron = require('electron')
const { app, BrowserWindow } = require('electron')
const config = require('../../config')
function init () {
const win = webtorrent.win = new electron.BrowserWindow({
const win = webtorrent.win = new BrowserWindow({
backgroundColor: '#1E1E1E',
backgroundThrottling: false, // do not throttle animations/timers when page is background
center: true,
fullscreen: false,
fullscreenable: false,
@@ -25,14 +24,22 @@ function init () {
skipTaskbar: true,
title: 'webtorrent-hidden-window',
useContentSize: true,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
enableBlinkFeatures: 'AudioVideoTracks',
enableRemoteModule: true,
backgroundThrottling: false
},
width: 150
})
require('@electron/remote/main').enable(win.webContents)
win.loadURL(config.WINDOW_WEBTORRENT)
// Prevent killing the WebTorrent process
win.on('close', function (e) {
if (electron.app.isQuitting) {
win.on('close', e => {
if (app.isQuitting) {
return
}
e.preventDefault()
@@ -56,6 +63,6 @@ function toggleDevTools () {
webtorrent.win.webContents.closeDevTools()
webtorrent.win.hide()
} else {
webtorrent.win.webContents.openDevTools({ detach: true })
webtorrent.win.webContents.openDevTools({ mode: 'detach' })
}
}

View File

@@ -0,0 +1,31 @@
const React = require('react')
const ModalOKCancel = require('./modal-ok-cancel')
const { dispatch, dispatcher } = require('../lib/dispatcher')
module.exports = class DeleteAllTorrentsModal extends React.Component {
render () {
const { state: { modal: { deleteData } } } = this.props
const message = deleteData
? 'Are you sure you want to remove all the torrents from the list and delete the data files?'
: 'Are you sure you want to remove all the torrents from the list?'
const buttonText = deleteData ? 'REMOVE DATA' : 'REMOVE'
return (
<div>
<p><strong>{message}</strong></p>
<ModalOKCancel
cancelText='CANCEL'
onCancel={dispatcher('exitModal')}
okText={buttonText}
onOK={handleRemove}
/>
</div>
)
function handleRemove () {
dispatch('deleteAllTorrents', deleteData)
dispatch('exitModal')
}
}
}

View File

@@ -6,22 +6,33 @@ class Header extends React.Component {
render () {
const loc = this.props.state.location
return (
<div className='header'
<div
className='header'
onMouseMove={dispatcher('mediaMouseMoved')}
onMouseEnter={dispatcher('mediaControlsMouseEnter')}
onMouseLeave={dispatcher('mediaControlsMouseLeave')}>
onMouseLeave={dispatcher('mediaControlsMouseLeave')}
role='navigation'
>
{this.getTitle()}
<div className='nav left float-left'>
<i
className={'icon back ' + (loc.hasBack() ? '' : 'disabled')}
title='Back'
onClick={dispatcher('back')}>
onClick={dispatcher('back')}
role='button'
aria-disabled={!loc.hasBack()}
aria-label='Back'
>
chevron_left
</i>
<i
className={'icon forward ' + (loc.hasForward() ? '' : 'disabled')}
title='Forward'
onClick={dispatcher('forward')}>
onClick={dispatcher('forward')}
role='button'
aria-disabled={!loc.hasForward()}
aria-label='Forward'
>
chevron_right
</i>
</div>
@@ -45,7 +56,9 @@ class Header extends React.Component {
<i
className='icon add'
title='Add torrent'
onClick={dispatcher('openFiles')}>
onClick={dispatcher('openFiles')}
role='button'
>
add
</i>
)

View File

@@ -1,11 +1,12 @@
const React = require('react')
const PropTypes = require('prop-types')
const colors = require('material-ui/styles/colors')
class Heading extends React.Component {
static get propTypes () {
return {
level: React.PropTypes.number
level: PropTypes.number
}
}

View File

@@ -12,13 +12,15 @@ module.exports = class ModalOKCancel extends React.Component {
className='control cancel'
style={cancelStyle}
label={cancelText}
onClick={onCancel} />
onClick={onCancel}
/>
<RaisedButton
className='control ok'
primary
label={okText}
onClick={onOK}
autoFocus />
autoFocus
/>
</div>
)
}

View File

@@ -1,8 +1,10 @@
const React = require('react')
const TextField = require('material-ui/TextField').default
const { clipboard } = require('electron')
const ModalOKCancel = require('./modal-ok-cancel')
const { dispatch, dispatcher } = require('../lib/dispatcher')
const { isMagnetLink } = require('../lib/torrent-player')
module.exports = class OpenTorrentAddressModal extends React.Component {
render () {
@@ -15,19 +17,27 @@ module.exports = class OpenTorrentAddressModal extends React.Component {
className='control'
ref={(c) => { this.torrentURL = c }}
fullWidth
onKeyDown={handleKeyDown.bind(this)} />
onKeyDown={handleKeyDown.bind(this)}
/>
</div>
<ModalOKCancel
cancelText='CANCEL'
onCancel={dispatcher('exitModal')}
okText='OK'
onOK={handleOK.bind(this)} />
onOK={handleOK.bind(this)}
/>
</div>
)
}
componentDidMount () {
this.torrentURL.input.focus()
const clipboardContent = clipboard.readText()
if (isMagnetLink(clipboardContent)) {
this.torrentURL.input.value = clipboardContent
this.torrentURL.input.select()
}
}
}

View File

@@ -1,8 +1,9 @@
const colors = require('material-ui/styles/colors')
const electron = require('electron')
const React = require('react')
const path = require('path')
const remote = electron.remote
const colors = require('material-ui/styles/colors')
const remote = require('@electron/remote')
const React = require('react')
const PropTypes = require('prop-types')
const RaisedButton = require('material-ui/RaisedButton').default
const TextField = require('material-ui/TextField').default
@@ -11,15 +12,14 @@ const TextField = require('material-ui/TextField').default
// Uses the system Open File dialog.
// You can't edit the text field directly.
class PathSelector extends React.Component {
static get propTypes () {
static propTypes () {
return {
className: React.PropTypes.string,
dialog: React.PropTypes.object,
displayValue: React.PropTypes.string,
id: React.PropTypes.string,
onChange: React.PropTypes.func,
title: React.PropTypes.string.isRequired,
value: React.PropTypes.string
className: PropTypes.string,
dialog: PropTypes.object,
id: PropTypes.string,
onChange: PropTypes.func,
title: PropTypes.string.isRequired,
value: PropTypes.string
}
}
@@ -30,18 +30,13 @@ class PathSelector extends React.Component {
handleClick () {
const opts = Object.assign({
defaultPath: this.props.value,
properties: [ 'openFile', 'openDirectory' ]
defaultPath: path.dirname(this.props.value || ''),
properties: ['openFile', 'openDirectory']
}, this.props.dialog)
remote.dialog.showOpenDialog(
remote.getCurrentWindow(),
opts,
(filenames) => {
if (!Array.isArray(filenames)) return
this.props.onChange && this.props.onChange(filenames[0])
}
)
const filenames = remote.dialog.showOpenDialogSync(remote.getCurrentWindow(), opts)
if (!Array.isArray(filenames)) return
this.props.onChange && this.props.onChange(filenames[0])
}
render () {
@@ -64,7 +59,7 @@ class PathSelector extends React.Component {
const textFieldStyle = {
flex: '1'
}
const text = this.props.displayValue || this.props.value
const text = this.props.value || ''
const buttonStyle = {
marginLeft: 10
}
@@ -74,10 +69,14 @@ class PathSelector extends React.Component {
<div className='label' style={labelStyle}>
{this.props.title}:
</div>
<TextField className='control' disabled id={id} value={text}
inputStyle={textareaStyle} style={textFieldStyle} />
<RaisedButton className='control' label='Change' onClick={this.handleClick}
style={buttonStyle} />
<TextField
className='control' disabled id={id} value={text}
inputStyle={textareaStyle} style={textFieldStyle}
/>
<RaisedButton
className='control' label='Change' onClick={this.handleClick}
style={buttonStyle}
/>
</div>
)
}

View File

@@ -18,7 +18,8 @@ module.exports = class RemoveTorrentModal extends React.Component {
cancelText='CANCEL'
onCancel={dispatcher('exitModal')}
okText={buttonText}
onOK={handleRemove} />
onOK={handleRemove}
/>
</div>
)

View File

@@ -1,13 +1,14 @@
const React = require('react')
const PropTypes = require('prop-types')
const RaisedButton = require('material-ui/RaisedButton').default
class ShowMore extends React.Component {
static get propTypes () {
return {
defaultExpanded: React.PropTypes.bool,
hideLabel: React.PropTypes.string,
showLabel: React.PropTypes.string
defaultExpanded: PropTypes.bool,
hideLabel: PropTypes.string,
showLabel: PropTypes.string
}
}
@@ -44,7 +45,8 @@ class ShowMore extends React.Component {
<RaisedButton
className='control'
onClick={this.handleClick}
label={label} />
label={label}
/>
</div>
)
}

View File

@@ -1,5 +1,5 @@
const React = require('react')
const electron = require('electron')
const { shell } = require('electron')
const ModalOKCancel = require('./modal-ok-cancel')
const { dispatcher } = require('../lib/dispatcher')
@@ -28,14 +28,15 @@ module.exports = class UnsupportedMediaModal extends React.Component {
cancelText='CANCEL'
onCancel={dispatcher('backToList')}
okText={actionText}
onOK={onAction} />
onOK={onAction}
/>
<p className='error-text'>{errorMessage}</p>
</div>
)
}
onInstall () {
electron.shell.openExternal('http://www.videolan.org/vlc/')
shell.openExternal('https://www.videolan.org/vlc/')
// TODO: dcposch send a dispatch rather than modifying state directly
const state = this.props.state

View File

@@ -1,5 +1,5 @@
const React = require('react')
const electron = require('electron')
const { shell } = require('electron')
const ModalOKCancel = require('./modal-ok-cancel')
const { dispatch } = require('../lib/dispatcher')
@@ -18,13 +18,14 @@ module.exports = class UpdateAvailableModal extends React.Component {
cancelText='SKIP THIS RELEASE'
onCancel={handleSkip}
okText='SHOW DOWNLOAD PAGE'
onOK={handleShow} />
onOK={handleShow}
/>
</div>
)
function handleShow () {
// TODO: use the GitHub urls from config.js
electron.shell.openExternal('https://github.com/webtorrent/webtorrent-desktop/releases')
shell.openExternal('https://github.com/webtorrent/webtorrent-desktop/releases')
dispatch('exitModal')
}

View File

@@ -0,0 +1,17 @@
const { dispatch } = require('../lib/dispatcher')
module.exports = class AudioTracksController {
constructor (state) {
this.state = state
}
selectAudioTrack (ix) {
this.state.playing.audioTracks.selectedIndex = ix
dispatch('skip', 0.2) // HACK: hardcoded seek value for smooth audio change
}
toggleAudioTracksMenu () {
const audioTracks = this.state.playing.audioTracks
audioTracks.showMenu = !audioTracks.showMenu
}
}

View File

@@ -23,10 +23,10 @@ module.exports = class MediaController {
telemetry.logPlayAttempt('error')
state.playing.location = 'error'
ipcRenderer.send('checkForExternalPlayer', state.saved.prefs.externalPlayerPath)
ipcRenderer.once('checkForExternalPlayer', function (e, isInstalled) {
ipcRenderer.once('checkForExternalPlayer', (e, isInstalled) => {
state.modal = {
id: 'unsupported-media-modal',
error: error,
error,
externalPlayerInstalled: isInstalled
}
})
@@ -56,7 +56,7 @@ module.exports = class MediaController {
const state = this.state
state.playing.location = 'external'
const onServerRunning = function () {
const onServerRunning = () => {
state.playing.isReady = true
telemetry.logPlayAttempt('external')

View File

@@ -1,4 +1,4 @@
const electron = require('electron')
const { ipcRenderer } = require('electron')
const path = require('path')
const Cast = require('../lib/cast')
@@ -11,8 +11,6 @@ const TorrentSummary = require('../lib/torrent-summary')
const Playlist = require('../lib/playlist')
const State = require('../lib/state')
const ipcRenderer = electron.ipcRenderer
// Controls playback of torrents and files within torrents
// both local (<video>,<audio>,external player) and remote (cast)
module.exports = class PlaybackController {
@@ -61,12 +59,12 @@ module.exports = class PlaybackController {
}
// Open a file in OS default app.
openItem (infoHash, index) {
openPath (infoHash, index) {
const torrentSummary = TorrentSummary.getByKey(this.state, infoHash)
const filePath = path.join(
torrentSummary.path,
torrentSummary.files[index].path)
ipcRenderer.send('openItem', filePath)
ipcRenderer.send('openPath', filePath)
}
// Toggle (play or pause) the currently playing media
@@ -158,6 +156,20 @@ module.exports = class PlaybackController {
else this.state.playing.jumpToTime = time
}
// Show video preview
preview (x) {
if (!Number.isFinite(x)) {
console.error('Tried to preview a non-finite position ' + x)
return console.trace()
}
this.state.playing.previewXCoord = x
}
// Hide video preview
clearPreview () {
this.state.playing.previewXCoord = null
}
// Change playback speed. 1 = faster, -1 = slower
// Playback speed ranges from 16 (fast forward) to 1 (normal playback)
// to 0.25 (quarter-speed playback), then goes to -0.25, -0.5, -1, -2, etc
@@ -269,8 +281,11 @@ module.exports = class PlaybackController {
// update state
state.playing.infoHash = infoHash
state.playing.fileIndex = index
state.playing.type = TorrentPlayer.isVideo(fileSummary) ? 'video'
: TorrentPlayer.isAudio(fileSummary) ? 'audio'
state.playing.fileName = fileSummary.name
state.playing.type = TorrentPlayer.isVideo(fileSummary)
? 'video'
: TorrentPlayer.isAudio(fileSummary)
? 'audio'
: 'other'
// pick up where we left off

View File

@@ -1,5 +1,5 @@
const { dispatch } = require('../lib/dispatcher')
const ipcRenderer = require('electron').ipcRenderer
const { ipcRenderer } = require('electron')
// Controls the Preferences screen
module.exports = class PrefsController {
@@ -13,7 +13,7 @@ module.exports = class PrefsController {
const state = this.state
state.location.go({
url: 'preferences',
setup: function (cb) {
setup (cb) {
// initialize preferences
state.window.title = 'Preferences'
ipcRenderer.send('setAllowNav', false)

View File

@@ -1,10 +1,8 @@
const electron = require('electron')
const remote = require('@electron/remote')
const fs = require('fs')
const path = require('path')
const parallel = require('run-parallel')
const remote = electron.remote
const { dispatch } = require('../lib/dispatcher')
module.exports = class SubtitlesController {
@@ -13,14 +11,13 @@ module.exports = class SubtitlesController {
}
openSubtitles () {
remote.dialog.showOpenDialog({
const filenames = remote.dialog.showOpenDialogSync({
title: 'Select a subtitles file.',
filters: [ { name: 'Subtitles', extensions: ['vtt', 'srt'] } ],
properties: [ 'openFile' ]
}, (filenames) => {
if (!Array.isArray(filenames)) return
this.addSubtitles(filenames, true)
filters: [{ name: 'Subtitles', extensions: ['vtt', 'srt'] }],
properties: ['openFile']
})
if (!Array.isArray(filenames)) return
this.addSubtitles(filenames, true)
}
selectSubtitle (ix) {
@@ -40,12 +37,11 @@ module.exports = class SubtitlesController {
// Read the files concurrently, then add all resulting subtitle tracks
const tasks = files.map((file) => (cb) => loadSubtitle(file, cb))
parallel(tasks, function (err, tracks) {
parallel(tasks, (err, tracks) => {
if (err) return dispatch('error', err)
for (let i = 0; i < tracks.length; i++) {
// No dupes allowed
const track = tracks[i]
// No dupes allowed
tracks.forEach((track, i) => {
let trackIndex = subtitles.tracks.findIndex((t) =>
track.filePath === t.filePath)
@@ -58,7 +54,7 @@ module.exports = class SubtitlesController {
if (autoSelect && (i === 0 || isSystemLanguage(track.language))) {
subtitles.selectedIndex = trackIndex
}
}
})
// Finally, make sure no two tracks have the same label
relabelSubtitles(subtitles)
@@ -97,7 +93,7 @@ function loadSubtitle (file, cb) {
const vttStream = fs.createReadStream(filePath).pipe(srtToVtt())
concat(vttStream, function (err, buf) {
concat(vttStream, (err, buf) => {
if (err) return dispatch('error', 'Can\'t parse subtitles file.')
// Detect what language the subtitles are in
@@ -110,7 +106,7 @@ function loadSubtitle (file, cb) {
buffer: 'data:text/vtt;base64,' + buf.toString('base64'),
language: langDetected,
label: langDetected,
filePath: filePath
filePath
}
cb(null, track)
@@ -130,7 +126,7 @@ function isSystemLanguage (language) {
// Labels each track by language, eg 'German', 'English', 'English 2', ...
function relabelSubtitles (subtitles) {
const counts = {}
subtitles.tracks.forEach(function (track) {
subtitles.tracks.forEach(track => {
const lang = track.language
counts[lang] = (counts[lang] || 0) + 1
track.label = counts[lang] > 1 ? (lang + ' ' + counts[lang]) : lang

View File

@@ -1,5 +1,5 @@
const path = require('path')
const ipcRenderer = require('electron').ipcRenderer
const { ipcRenderer } = require('electron')
const TorrentSummary = require('../lib/torrent-summary')
const sound = require('../lib/sound')
@@ -10,7 +10,7 @@ module.exports = class TorrentController {
this.state = state
}
torrentInfoHash (torrentKey, infoHash) {
torrentParsed (torrentKey, infoHash, magnetURI) {
let torrentSummary = this.getTorrentSummary(torrentKey)
console.log('got infohash for %s torrent %s',
torrentSummary ? 'existing' : 'new', torrentKey)
@@ -25,7 +25,7 @@ module.exports = class TorrentController {
}
torrentSummary = {
torrentKey: torrentKey,
torrentKey,
status: 'new'
}
torrents.unshift(torrentSummary)
@@ -33,6 +33,7 @@ module.exports = class TorrentController {
}
torrentSummary.infoHash = infoHash
torrentSummary.magnetURI = magnetURI
dispatch('update')
}
@@ -62,7 +63,6 @@ module.exports = class TorrentController {
torrentSummary.status = 'downloading'
torrentSummary.name = torrentSummary.displayName || torrentInfo.name
torrentSummary.path = torrentInfo.path
torrentSummary.magnetURI = torrentInfo.magnetURI
// TODO: make torrentInfo immutable, save separately as torrentSummary.info
// For now, check whether torrentSummary.files has already been set:
const hasDetailedFileInfo = torrentSummary.files && torrentSummary.files[0].path
@@ -177,7 +177,7 @@ function showDoneNotification (torrent) {
silent: true
})
notif.onclick = function () {
notif.onclick = () => {
ipcRenderer.send('show')
}

View File

@@ -1,14 +1,13 @@
const fs = require('fs')
const path = require('path')
const electron = require('electron')
const { ipcRenderer, clipboard } = require('electron')
const remote = require('@electron/remote')
const { dispatch } = require('../lib/dispatcher')
const { TorrentKeyNotFoundError } = require('../lib/errors')
const sound = require('../lib/sound')
const TorrentSummary = require('../lib/torrent-summary')
const ipcRenderer = electron.ipcRenderer
const instantIoRegex = /^(https:\/\/)?instant\.io\/#/
// Controls the torrent list: creating, adding, deleting, & manipulating torrents
@@ -55,7 +54,7 @@ module.exports = class TorrentListController {
if (files.length === 0 || typeof files[0] !== 'string') {
this.state.location.go({
url: 'create-torrent',
files: files,
files,
setup: (cb) => {
this.state.window.title = 'Create New Torrent'
cb(null)
@@ -95,7 +94,7 @@ module.exports = class TorrentListController {
if (!fileOrFolder) return start()
// Existing torrent: check that the path is still there
fs.stat(fileOrFolder, function (err) {
fs.stat(fileOrFolder, err => {
if (err) {
s.error = 'path-missing'
dispatch('backToList')
@@ -114,6 +113,10 @@ module.exports = class TorrentListController {
}
}
setGlobalTrackers (globalTrackers) {
ipcRenderer.send('wt-set-global-trackers', globalTrackers)
}
// TODO: use torrentKey, not infoHash
toggleTorrent (infoHash) {
const torrentSummary = TorrentSummary.getByKey(this.state, infoHash)
@@ -157,10 +160,8 @@ module.exports = class TorrentListController {
prioritizeTorrent (infoHash) {
this.state.saved.torrents
.filter((torrent) => { // We're interested in active torrents only.
return (['downloading', 'seeding'].indexOf(torrent.status) !== -1)
})
.map((torrent) => { // Pause all active torrents except the one that started playing.
.filter(torrent => ['downloading', 'seeding'].includes(torrent.status)) // Active torrents only.
.forEach((torrent) => { // Pause all active torrents except the one that started playing.
if (infoHash === torrent.infoHash) return
// Pause torrent without playing sounds.
@@ -175,7 +176,7 @@ module.exports = class TorrentListController {
resumePausedTorrents () {
console.log('Playback Priority: resuming paused torrents')
if (!this.state.saved.torrentsToResume || !this.state.saved.torrentsToResume.length) return
this.state.saved.torrentsToResume.map((infoHash) => {
this.state.saved.torrentsToResume.forEach((infoHash) => {
this.toggleTorrent(infoHash)
})
@@ -201,26 +202,43 @@ module.exports = class TorrentListController {
}
}
confirmDeleteAllTorrents (deleteData) {
this.state.modal = {
id: 'delete-all-torrents-modal',
deleteData
}
}
// TODO: use torrentKey, not infoHash
deleteTorrent (infoHash, deleteData) {
ipcRenderer.send('wt-stop-torrenting', infoHash)
const index = this.state.saved.torrents.findIndex((x) => x.infoHash === infoHash)
if (index > -1) {
const summary = this.state.saved.torrents[index]
// remove torrent and poster file
deleteFile(TorrentSummary.getTorrentPath(summary))
deleteFile(TorrentSummary.getPosterPath(summary))
// optionally delete the torrent data
if (deleteData) moveItemToTrash(summary)
deleteTorrentFile(summary, deleteData)
// remove torrent from saved list
this.state.saved.torrents.splice(index, 1)
dispatch('stateSave')
// prevent user from going forward to a deleted torrent
this.state.location.clearForward('player')
sound.play('DELETE')
} else {
throw new TorrentKeyNotFoundError(infoHash)
}
}
deleteAllTorrents (deleteData) {
// Go back to list before the current playing torrent is deleted
if (this.state.location.url() === 'player') {
dispatch('backToList')
}
this.state.saved.torrents.forEach((summary) => deleteTorrentFile(summary, deleteData))
this.state.saved.torrents = []
dispatch('stateSave')
// prevent user from going forward to a deleted torrent
this.state.location.clearForward('player')
@@ -237,77 +255,88 @@ module.exports = class TorrentListController {
openTorrentContextMenu (infoHash) {
const torrentSummary = TorrentSummary.getByKey(this.state, infoHash)
const menu = new electron.remote.Menu()
const menu = new remote.Menu()
menu.append(new electron.remote.MenuItem({
menu.append(new remote.MenuItem({
label: 'Remove From List',
click: () => dispatch('confirmDeleteTorrent', torrentSummary.infoHash, false)
}))
menu.append(new electron.remote.MenuItem({
menu.append(new remote.MenuItem({
label: 'Remove Data File',
click: () => dispatch('confirmDeleteTorrent', torrentSummary.infoHash, true)
}))
menu.append(new electron.remote.MenuItem({
menu.append(new remote.MenuItem({
type: 'separator'
}))
if (torrentSummary.files) {
menu.append(new electron.remote.MenuItem({
menu.append(new remote.MenuItem({
label: process.platform === 'darwin' ? 'Show in Finder' : 'Show in Folder',
click: () => showItemInFolder(torrentSummary)
}))
menu.append(new electron.remote.MenuItem({
menu.append(new remote.MenuItem({
type: 'separator'
}))
}
menu.append(new electron.remote.MenuItem({
menu.append(new remote.MenuItem({
label: 'Copy Magnet Link to Clipboard',
click: () => electron.clipboard.writeText(torrentSummary.magnetURI)
click: () => clipboard.writeText(torrentSummary.magnetURI)
}))
menu.append(new electron.remote.MenuItem({
menu.append(new remote.MenuItem({
label: 'Copy Instant.io Link to Clipboard',
click: () => electron.clipboard.writeText(`https://instant.io/#${torrentSummary.infoHash}`)
click: () => clipboard.writeText(`https://instant.io/#${torrentSummary.infoHash}`)
}))
menu.append(new electron.remote.MenuItem({
menu.append(new remote.MenuItem({
label: 'Save Torrent File As...',
click: () => dispatch('saveTorrentFileAs', torrentSummary.torrentKey),
enabled: torrentSummary.torrentFileName != null
}))
menu.popup(electron.remote.getCurrentWindow())
menu.append(new remote.MenuItem({
type: 'separator'
}))
const sortedByName = this.state.saved.prefs.sortByName
menu.append(new remote.MenuItem({
label: `${sortedByName ? '✓ ' : ''}Sort by Name`,
click: () => dispatch('updatePreferences', 'sortByName', !sortedByName)
}))
menu.popup({ window: remote.getCurrentWindow() })
}
// Takes a torrentSummary or torrentKey
// Shows a Save File dialog, then saves the .torrent file wherever the user requests
saveTorrentFileAs (torrentKey) {
const torrentSummary = TorrentSummary.getByKey(this.state, torrentKey)
if (!torrentSummary) throw new Error('Missing torrentKey: ' + torrentKey)
if (!torrentSummary) throw new TorrentKeyNotFoundError(torrentKey)
const downloadPath = this.state.saved.prefs.downloadPath
const newFileName = path.parse(torrentSummary.name).name + '.torrent'
const win = electron.remote.getCurrentWindow()
const win = remote.getCurrentWindow()
const opts = {
title: 'Save Torrent File',
defaultPath: path.join(downloadPath, newFileName),
filters: [
{ name: 'Torrent Files', extensions: ['torrent'] },
{ name: 'All Files', extensions: ['*'] }
]
],
buttonLabel: 'Save'
}
electron.remote.dialog.showSaveDialog(win, opts, function (savePath) {
console.log('Saving torrent ' + torrentKey + ' to ' + savePath)
if (!savePath) return // They clicked Cancel
const torrentPath = TorrentSummary.getTorrentPath(torrentSummary)
fs.readFile(torrentPath, function (err, torrentFile) {
const savePath = remote.dialog.showSaveDialogSync(win, opts)
if (!savePath) return // They clicked Cancel
console.log('Saving torrent ' + torrentKey + ' to ' + savePath)
const torrentPath = TorrentSummary.getTorrentPath(torrentSummary)
fs.readFile(torrentPath, (err, torrentFile) => {
if (err) return dispatch('error', err)
fs.writeFile(savePath, torrentFile, err => {
if (err) return dispatch('error', err)
fs.writeFile(savePath, torrentFile, function (err) {
if (err) return dispatch('error', err)
})
})
})
}
@@ -318,12 +347,12 @@ module.exports = class TorrentListController {
function findFilesRecursive (paths, cb_) {
if (paths.length > 1) {
let numComplete = 0
let ret = []
paths.forEach(function (path) {
findFilesRecursive([path], function (fileObjs) {
const ret = []
paths.forEach(path => {
findFilesRecursive([path], fileObjs => {
ret.push(...fileObjs)
if (++numComplete === paths.length) {
ret.sort((a, b) => a.path < b.path ? -1 : a.path > b.path)
ret.sort((a, b) => a.path < b.path ? -1 : Number(a.path > b.path))
cb_(ret)
}
})
@@ -332,7 +361,7 @@ function findFilesRecursive (paths, cb_) {
}
const fileOrFolder = paths[0]
fs.stat(fileOrFolder, function (err, stat) {
fs.stat(fileOrFolder, (err, stat) => {
if (err) return dispatch('error', err)
// Files: return name, path, and size
@@ -347,7 +376,7 @@ function findFilesRecursive (paths, cb_) {
// Folders: recurse, make a list of all the files
const folderPath = fileOrFolder
fs.readdir(folderPath, function (err, fileNames) {
fs.readdir(folderPath, (err, fileNames) => {
if (err) return dispatch('error', err)
const paths = fileNames.map((fileName) => path.join(folderPath, fileName))
findFilesRecursive(paths, cb_)
@@ -357,7 +386,7 @@ function findFilesRecursive (paths, cb_) {
function deleteFile (path) {
if (!path) return
fs.unlink(path, function (err) {
fs.unlink(path, err => {
if (err) dispatch('error', err)
})
}
@@ -371,3 +400,14 @@ function moveItemToTrash (torrentSummary) {
function showItemInFolder (torrentSummary) {
ipcRenderer.send('showItemInFolder', TorrentSummary.getFileOrFolder(torrentSummary))
}
function deleteTorrentFile (torrentSummary, deleteData) {
ipcRenderer.send('wt-stop-torrenting', torrentSummary.infoHash)
// remove torrent and poster file
deleteFile(TorrentSummary.getTorrentPath(torrentSummary))
deleteFile(TorrentSummary.getPosterPath(torrentSummary))
// optionally delete the torrent data
if (deleteData) moveItemToTrash(torrentSummary)
}

View File

@@ -13,7 +13,7 @@ module.exports = class UpdateController {
console.log('new version skipped by user: v' + version)
return
}
this.state.modal = { id: 'update-available-modal', version: version }
this.state.modal = { id: 'update-available-modal', version }
}
// Don't show the modal again until the next version

View File

@@ -54,17 +54,17 @@ function init (appState, callback) {
state.devices.airplay = airplayPlayer()
// Listen for devices: Chromecast, DLNA and Airplay
chromecasts.on('update', function (device) {
chromecasts.on('update', device => {
// TODO: how do we tell if there are *no longer* any Chromecasts available?
// From looking at the code, chromecasts.players only grows, never shrinks
state.devices.chromecast.addDevice(device)
})
dlnacasts.on('update', function (device) {
dlnacasts.on('update', device => {
state.devices.dlna.addDevice(device)
})
airplayer.on('update', function (device) {
airplayer.on('update', device => {
state.devices.airplay.addDevice(device)
})
}
@@ -116,7 +116,7 @@ function chromecastPlayer () {
}
function addDevice (device) {
device.on('error', function (err) {
device.on('error', err => {
if (device !== ret.device) return
state.playing.location = 'local'
state.errors.push({
@@ -125,7 +125,7 @@ function chromecastPlayer () {
})
update()
})
device.on('disconnect', function () {
device.on('disconnect', () => {
if (device !== ret.device) return
state.playing.location = 'local'
update()
@@ -144,8 +144,8 @@ function chromecastPlayer () {
'Access-Control-Allow-Origin': '*',
'Transfer-Encoding': 'chunked'
})
res.end(Buffer.from(selectedSubtitle.buffer.substr(21), 'base64'))
}).listen(0, function () {
res.end(Buffer.from(selectedSubtitle.buffer.slice(21), 'base64'))
}).listen(0, () => {
const port = ret.subServer.address().port
const subtitlesUrl = 'http://' + state.server.networkAddress + ':' + port + '/'
callback(subtitlesUrl)
@@ -155,13 +155,13 @@ function chromecastPlayer () {
function open () {
const torrentSummary = state.saved.torrents.find((x) => x.infoHash === state.playing.infoHash)
serveSubtitles(function (subtitlesUrl) {
serveSubtitles(subtitlesUrl => {
ret.device.play(state.server.networkURL + '/' + state.playing.fileIndex, {
type: 'video/mp4',
title: config.APP_NAME + ' - ' + torrentSummary.name,
subtitles: subtitlesUrl ? [subtitlesUrl] : [],
autoSubtitles: !!subtitlesUrl
}, function (err) {
}, err => {
if (err) {
state.playing.location = 'local'
state.errors.push({
@@ -221,7 +221,7 @@ function airplayPlayer () {
return ret
function addDevice (player) {
player.on('event', function (event) {
player.on('event', event => {
switch (event.state) {
case 'loading':
break
@@ -243,7 +243,7 @@ function airplayPlayer () {
}
function open () {
ret.device.play(state.server.networkURL + '/' + state.playing.fileIndex, function (err, res) {
ret.device.play(state.server.networkURL + '/' + state.playing.fileIndex, (err, res) => {
if (err) {
state.playing.location = 'local'
state.errors.push({
@@ -270,7 +270,7 @@ function airplayPlayer () {
}
function status () {
ret.device.playbackInfo(function (err, res, status) {
ret.device.playbackInfo((err, res, status) => {
if (err) {
state.playing.location = 'local'
state.errors.push({
@@ -317,7 +317,7 @@ function dlnaPlayer (player) {
}
function addDevice (device) {
device.on('error', function (err) {
device.on('error', err => {
if (device !== ret.device) return
state.playing.location = 'local'
state.errors.push({
@@ -326,7 +326,7 @@ function dlnaPlayer (player) {
})
update()
})
device.on('disconnect', function () {
device.on('disconnect', () => {
if (device !== ret.device) return
state.playing.location = 'local'
update()
@@ -339,7 +339,7 @@ function dlnaPlayer (player) {
type: 'video/mp4',
title: config.APP_NAME + ' - ' + torrentSummary.name,
seek: state.playing.currentTime > 10 ? state.playing.currentTime : 0
}, function (err) {
}, err => {
if (err) {
state.playing.location = 'local'
state.errors.push({
@@ -374,7 +374,7 @@ function dlnaPlayer (player) {
}
function volume (volume, callback) {
ret.device.volume(volume, function (err) {
ret.device.volume(volume, err => {
// quick volume update
state.playing.volume = volume
callback(err)
@@ -396,7 +396,7 @@ function handleStatus (err, status) {
// Start polling cast device state, whenever we're connected
function startStatusInterval () {
statusInterval = setInterval(function () {
statusInterval = setInterval(() => {
const player = getPlayer()
if (player) player.status()
}, 1000)
@@ -454,7 +454,7 @@ function selectDevice (index) {
function stop () {
const player = getPlayer()
if (player) {
player.stop(function () {
player.stop(() => {
player.device = null
stoppedCasting()
})
@@ -522,6 +522,6 @@ function setVolume (volume) {
if (player) player.volume(volume, castCallback)
}
function castCallback () {
console.log('%s callback: %o', state.playing.location, arguments)
function castCallback (...args) {
console.log('%s callback: %o', state.playing.location, args)
}

View File

@@ -5,7 +5,7 @@ module.exports = {
}
const dispatchers = {}
let _dispatch = function () {}
let _dispatch = () => {}
function setDispatch (dispatch) {
_dispatch = dispatch
@@ -23,7 +23,7 @@ function dispatcher (...args) {
const str = JSON.stringify(args)
let handler = dispatchers[str]
if (!handler) {
handler = dispatchers[str] = function (e) {
handler = dispatchers[str] = e => {
// Do not propagate click to elements below the button
e.stopPropagation()

View File

@@ -1,10 +1,11 @@
const mediaExtensions = {
audio: [
'.aac', '.asf', '.flac', '.m2a', '.m4a', '.m4b', '.mp2', '.mp4',
'.mp3', '.oga', '.ogg', '.opus', '.wma', '.wav', '.wv', '.wvp'],
'.aac', '.aif', '.aiff', '.asf', '.dff', '.dsf', '.flac', '.m2a',
'.m2a', '.m4a', '.mpc', '.m4b', '.mka', '.mp2', '.mp3', '.mpc', '.oga',
'.ogg', '.opus', '.spx', '.wma', '.wav', '.wv', '.wvp'],
video: [
'.avi', '.mp4', '.m4v', '.webm', '.mov', '.mkv', 'mpg', 'mpeg',
'.ogv', '.webm', '.wmv'],
'.avi', '.mp4', '.m4v', '.webm', '.mov', '.mkv', '.mpg', '.mpeg',
'.ogv', '.webm', '.wmv', '.m2ts'],
image: ['.gif', '.jpg', '.jpeg', '.png']
}

View File

@@ -28,16 +28,31 @@ function run (state) {
if (semver.lt(version, '0.14.0')) migrate_0_14_0(saved)
if (semver.lt(version, '0.17.0')) migrate_0_17_0(saved)
if (semver.lt(version, '0.17.2')) migrate_0_17_2(saved)
if (semver.lt(version, '0.21.0')) migrate_0_21_0(saved)
if (semver.lt(version, '0.22.0')) migrate_0_22_0(saved)
if (semver.lt(version, config.APP_VERSION)) {
installHandlers(state.saved)
}
// Config is now on the new version
state.saved.version = config.APP_VERSION
}
// Whenever the app is updated, re-install default handlers if the user has
// enabled them.
function installHandlers (saved) {
if (saved.prefs.isFileHandler) {
const ipcRenderer = require('electron').ipcRenderer
ipcRenderer.send('setDefaultFileHandler', true)
}
}
function migrate_0_7_0 (saved) {
const cpFile = require('cp-file')
const { copyFileSync } = require('fs')
const path = require('path')
saved.torrents.forEach(function (ts) {
saved.torrents.forEach(ts => {
const infoHash = ts.infoHash
// Replace torrentPath with torrentFileName
@@ -56,7 +71,7 @@ function migrate_0_7_0 (saved) {
dst = path.join(config.TORRENT_PATH, infoHash + '.torrent')
// Synchronous FS calls aren't ideal, but probably OK in a migration
// that only runs once
if (src !== dst) cpFile.sync(src, dst)
if (src !== dst) copyFileSync(src, dst)
delete ts.torrentPath
ts.torrentFileName = infoHash + '.torrent'
@@ -71,7 +86,7 @@ function migrate_0_7_0 (saved) {
dst = path.join(config.POSTER_PATH, infoHash + extension)
// Synchronous FS calls aren't ideal, but probably OK in a migration
// that only runs once
if (src !== dst) cpFile.sync(src, dst)
if (src !== dst) copyFileSync(src, dst)
delete ts.posterURL
ts.posterFileName = infoHash + extension
@@ -119,7 +134,7 @@ function migrate_0_12_0 (saved) {
'02767050e0be2fd4db9a2ad6c12416ac806ed6ed.torrent',
'3ba219a8634bf7bae3d848192b2da75ae995589d.torrent'
]
saved.torrents.forEach(function (torrentSummary) {
saved.torrents.forEach(torrentSummary => {
if (!defaultTorrentFiles.includes(torrentSummary.torrentFileName)) return
const fileOrFolder = TorrentSummary.getFileOrFolder(torrentSummary)
if (!fileOrFolder) return
@@ -133,16 +148,16 @@ function migrate_0_12_0 (saved) {
}
function migrate_0_14_0 (saved) {
saved.torrents.forEach(function (ts) {
saved.torrents.forEach(ts => {
delete ts.defaultPlayFileIndex
})
}
function migrate_0_17_0 (saved) {
// Fix a sad, sad bug that resulted in 100MB+ config.json files
saved.torrents.forEach(function (ts) {
saved.torrents.forEach(ts => {
if (!ts.files) return
ts.files.forEach(function (file) {
ts.files.forEach(file => {
if (!file.audioInfo || !file.audioInfo.picture) return
// This contained a Buffer, which 30x'd in size when serialized to JSON
delete file.audioInfo.picture
@@ -155,7 +170,7 @@ function migrate_0_17_2 (saved) {
// folders/files that end in a trailing dot (.) or space are not deletable from
// Windows Explorer. See: https://github.com/webtorrent/webtorrent-desktop/issues/905
const cpFile = require('cp-file')
const { copyFileSync } = require('fs')
const rimraf = require('rimraf')
const OLD_NAME = 'The WIRED CD - Rip. Sample. Mash. Share.'
@@ -164,9 +179,7 @@ function migrate_0_17_2 (saved) {
const OLD_HASH = '3ba219a8634bf7bae3d848192b2da75ae995589d'
const NEW_HASH = 'a88fda5954e89178c372716a6a78b8180ed4dad3'
const ts = saved.torrents.find((ts) => {
return ts.infoHash === OLD_HASH
})
const ts = saved.torrents.find(ts => ts.infoHash === OLD_HASH)
if (!ts) return // Wired CD torrent does not exist
@@ -190,7 +203,7 @@ function migrate_0_17_2 (saved) {
ts.posterFileName = NEW_HASH + '.jpg'
rimraf.sync(path.join(config.TORRENT_PATH, ts.torrentFileName))
cpFile.sync(
copyFileSync(
path.join(config.STATIC_PATH, 'wiredCd.torrent'),
path.join(config.TORRENT_PATH, NEW_HASH + '.torrent')
)
@@ -206,3 +219,16 @@ function migrate_0_17_2 (saved) {
} catch (err) {}
}
}
function migrate_0_21_0 (saved) {
if (saved.prefs.soundNotifications == null) {
// The app used to always have sound notifications enabled
saved.prefs.soundNotifications = true
}
}
function migrate_0_22_0 (saved) {
if (saved.prefs.externalPlayerPath == null) {
saved.prefs.externalPlayerPath = ''
}
}

View File

@@ -38,7 +38,8 @@ function getPreviousIndex (state) {
function getCurrentLocalURL (state) {
return state.server
? state.server.localURL + '/' + state.playing.fileIndex
? state.server.localURL + '/' + state.playing.fileIndex + '/' +
encodeURIComponent(state.playing.fileName)
: ''
}

View File

@@ -1,4 +1,5 @@
module.exports = {
init,
play
}
@@ -8,6 +9,9 @@ const path = require('path')
const VOLUME = 0.25
// App state to access the soundNotifications preference
let state
/* Cache of Audio elements, for instant playback */
const cache = {}
@@ -46,7 +50,19 @@ const sounds = {
}
}
function init (appState) {
state = appState
}
function play (name) {
if (state == null) {
return
}
if (!state.saved.prefs.soundNotifications) {
return
}
let audio = cache[name]
if (!audio) {
const sound = sounds[name]

View File

@@ -3,6 +3,7 @@ const path = require('path')
const { EventEmitter } = require('events')
const config = require('../../config')
const defaultAnnounceList = require('create-torrent').announceList.map((arr) => arr[0])
const SAVE_DEBOUNCE_INTERVAL = 1000
@@ -12,13 +13,13 @@ const State = module.exports = Object.assign(new EventEmitter(), {
getDefaultPlayState,
load,
// state.save() calls are rate-limited. Use state.saveImmediate() to skip limit.
save: function () {
save (...args) {
// Perf optimization: Lazy-require debounce (and it's dependencies)
const debounce = require('debounce')
// After first State.save() invokation, future calls go straight to the
// debounced function
State.save = debounce(saveImmediate, SAVE_DEBOUNCE_INTERVAL)
State.save(...arguments)
State.save(...args)
},
saveImmediate
})
@@ -79,6 +80,7 @@ function getDefaultState () {
getPlayingTorrentSummary,
getPlayingFileSummary,
getExternalPlayerName,
getGlobalTrackers,
shouldHidePlayerControls
}
}
@@ -88,6 +90,7 @@ function getDefaultPlayState () {
return {
infoHash: null, /* the info hash of the torrent we're playing */
fileIndex: null, /* the zero-based index within the torrent */
fileName: null, /* name of the file that is playing */
location: 'local', /* 'local', 'chromecast', 'airplay' */
type: null, /* 'audio' or 'video', could be 'other' if ever support eg streaming to VLC */
currentTime: 0, /* seconds */
@@ -104,14 +107,18 @@ function getDefaultPlayState () {
selectedIndex: -1, /* current subtitle track */
showMenu: false /* popover menu, above the video */
},
audioTracks: {
tracks: [],
selectedIndex: 0, /* current audio track */
showMenu: false /* popover menu, above the video */
},
aspectRatio: 0 /* aspect ratio of the video */
}
}
/* If the saved state file doesn't exist yet, here's what we use instead */
function setupStateSaved (cb) {
const cpFile = require('cp-file')
const fs = require('fs')
function setupStateSaved () {
const { copyFileSync, mkdirSync, readFileSync } = require('fs')
const parseTorrent = require('parse-torrent')
const saved = {
@@ -119,42 +126,41 @@ function setupStateSaved (cb) {
downloadPath: config.DEFAULT_DOWNLOAD_PATH,
isFileHandler: false,
openExternalPlayer: false,
externalPlayerPath: null,
externalPlayerPath: '',
startup: false,
soundNotifications: true,
autoAddTorrents: false,
torrentsFolderPath: '',
highestPlaybackPriority: true
highestPlaybackPriority: true,
globalTrackers: defaultAnnounceList
},
torrents: config.DEFAULT_TORRENTS.map(createTorrentObject),
torrentsToResume: [],
version: config.APP_VERSION /* make sure we can upgrade gracefully later */
}
const tasks = []
// TODO: Doing several sync calls during first startup is not ideal
mkdirSync(config.POSTER_PATH, { recursive: true })
mkdirSync(config.TORRENT_PATH, { recursive: true })
config.DEFAULT_TORRENTS.forEach((t, i) => {
const infoHash = saved.torrents[i].infoHash
tasks.push(
cpFile(
path.join(config.STATIC_PATH, t.posterFileName),
path.join(config.POSTER_PATH, infoHash + path.extname(t.posterFileName))
)
// TODO: Doing several sync calls during first startup is not ideal
copyFileSync(
path.join(config.STATIC_PATH, t.posterFileName),
path.join(config.POSTER_PATH, infoHash + path.extname(t.posterFileName))
)
tasks.push(
cpFile(
path.join(config.STATIC_PATH, t.torrentFileName),
path.join(config.TORRENT_PATH, infoHash + '.torrent')
)
copyFileSync(
path.join(config.STATIC_PATH, t.torrentFileName),
path.join(config.TORRENT_PATH, infoHash + '.torrent')
)
})
Promise.all(tasks)
.then(() => cb(null, saved))
.catch(err => cb(err))
return saved
function createTorrentObject (t) {
// TODO: Doing several fs.readFileSync calls during first startup is not ideal
const torrent = fs.readFileSync(path.join(config.STATIC_PATH, t.torrentFileName))
// TODO: Doing several sync calls during first startup is not ideal
const torrent = readFileSync(path.join(config.STATIC_PATH, t.torrentFileName))
const parsedTorrent = parseTorrent(torrent)
return {
@@ -195,19 +201,31 @@ function shouldHidePlayerControls () {
new Date().getTime() - this.playing.mouseStationarySince > 2000 &&
!this.playing.mouseInControls &&
!this.playing.isPaused &&
this.playing.location === 'local' &&
this.playing.playbackRate === 1
this.playing.location === 'local'
}
function load (cb) {
appConfig.read(function (err, saved) {
if (err || !saved.version) {
console.log('Missing config file: Creating new one')
setupStateSaved(onSavedState)
} else {
onSavedState(null, saved)
function getGlobalTrackers () {
const trackers = this.saved.prefs.globalTrackers
if (!trackers) {
return defaultAnnounceList
}
return trackers
}
async function load (cb) {
let saved = await appConfig.read()
if (!saved || !saved.version) {
console.log('Missing config file: Creating new one')
try {
saved = setupStateSaved()
} catch (err) {
onSavedState(err)
return
}
})
}
onSavedState(null, saved)
function onSavedState (err, saved) {
if (err) return cb(err)
@@ -225,7 +243,7 @@ function load (cb) {
}
// Write state.saved to the JSON state file
function saveImmediate (state, cb) {
async function saveImmediate (state, cb) {
console.log('Saving state to ' + appConfig.filePath)
// Clean up, so that we're not saving any pending state
@@ -234,9 +252,9 @@ function saveImmediate (state, cb) {
// reading the torrent file or file(s) to seed & don't have an infohash
copy.torrents = copy.torrents
.filter((x) => x.infoHash)
.map(function (x) {
.map(x => {
const torrent = {}
for (let key in x) {
for (const key in x) {
if (key === 'progress' || key === 'torrentKey') {
continue // Don't save progress info or key for the webtorrent process
}
@@ -248,8 +266,10 @@ function saveImmediate (state, cb) {
return torrent
})
appConfig.write(copy, (err) => {
if (err) console.error(err)
else State.emit('stateSaved')
})
try {
await appConfig.write(copy)
State.emit('stateSaved')
} catch (err) {
console.error(err)
}
}

View File

@@ -7,7 +7,7 @@ module.exports = {
logPlayAttempt
}
const electron = require('electron')
const remote = require('@electron/remote')
const config = require('../../config')
@@ -50,7 +50,7 @@ function send (state) {
json: true
}
get.post(opts, function (err, res) {
get.post(opts, (err, res) => {
if (err) return console.error('Error sending telemetry', err)
if (res.statusCode !== 200) {
return console.error(`Error sending telemetry, status code: ${res.statusCode}`)
@@ -74,7 +74,7 @@ function reset () {
// Track screen resolution
function getScreenInfo () {
return electron.screen.getAllDisplays().map((screen) => ({
return remote.screen.getAllDisplays().map((screen) => ({
width: screen.size.width,
height: screen.size.height,
scaleFactor: screen.scaleFactor
@@ -98,7 +98,7 @@ function getSystemInfo () {
function getTorrentStats (state) {
const count = state.saved.torrents.length
let sizeMB = 0
let byStatus = {
const byStatus = {
new: { count: 0, sizeMB: 0 },
downloading: { count: 0, sizeMB: 0 },
seeding: { count: 0, sizeMB: 0 },
@@ -106,15 +106,14 @@ function getTorrentStats (state) {
}
// First, count torrents & total file size
for (let i = 0; i < count; i++) {
const t = state.saved.torrents[i]
const stat = byStatus[t.status]
if (!t || !t.files || !stat) continue
for (const torrent of state.saved.torrents) {
const stat = byStatus[torrent.status]
if (!torrent || !torrent.files || !stat) continue
stat.count++
for (let j = 0; j < t.files.length; j++) {
const f = t.files[j]
if (!f || !f.length) continue
const fileSizeMB = f.length / (1 << 20)
for (const file of torrent.files) {
if (!file || !file.length) continue
const fileSizeMB = file.length / (1 << 20)
sizeMB += fileSizeMB
stat.sizeMB += fileSizeMB
}
@@ -145,7 +144,7 @@ function roundPow2 (n) {
if (n <= 0) return 0
// Otherwise, return 1, 2, 4, 8, etc by rounding in log space
const log2 = Math.log(n) / Math.log(2)
return Math.pow(2, Math.round(log2))
return 2 ** Math.round(log2)
}
// An uncaught error happened in the main process or in one of the windows

20
src/renderer/lib/time.js Normal file
View File

@@ -0,0 +1,20 @@
module.exports = {
calculateEta
}
function calculateEta (missing, downloadSpeed) {
if (downloadSpeed === 0 || missing === 0) return
const rawEta = missing / downloadSpeed
const hours = Math.floor(rawEta / 3600) % 24
const minutes = Math.floor(rawEta / 60) % 60
const seconds = Math.floor(rawEta % 60)
// Only display hours and minutes if they are greater than 0 but always
// display minutes if hours is being displayed
const hoursStr = hours ? hours + ' h' : ''
const minutesStr = (hours || minutes) ? minutes + ' min' : ''
const secondsStr = seconds + ' s'
return `${hoursStr} ${minutesStr} ${secondsStr} remaining`
}

View File

@@ -3,6 +3,7 @@ module.exports = {
isVideo,
isAudio,
isTorrent,
isMagnetLink,
isPlayableTorrentSummary
}
@@ -31,9 +32,15 @@ function isAudio (file) {
// - a file object where obj.name is ends in .torrent
// - a string that's a magnet link (magnet://...)
function isTorrent (file) {
const isTorrentFile = getFileExtension(file) === '.torrent'
const isMagnet = typeof file === 'string' && /^(stream-)?magnet:/.test(file)
return isTorrentFile || isMagnet
return isTorrentFile(file) || isMagnetLink(file)
}
function isTorrentFile (file) {
return getFileExtension(file) === '.torrent'
}
function isMagnetLink (link) {
return typeof link === 'string' && /^(stream-)?magnet:/.test(link)
}
function getFileExtension (file) {

View File

@@ -9,19 +9,14 @@ const msgNoSuitablePoster = 'Cannot generate a poster from any files in the torr
function torrentPoster (torrent, cb) {
// First, try to use a poster image if available
const posterFile = torrent.files.filter(function (file) {
return /^poster\.(jpg|png|gif)$/.test(file.name)
})[0]
const posterFile = torrent.files.filter(file => /^poster\.(jpg|png|gif)$/.test(file.name))[0]
if (posterFile) return extractPoster(posterFile, cb)
// 'score' each media type based on total size present in torrent
const bestScore = ['audio', 'video', 'image'].map(mediaType => {
return {
type: mediaType,
size: calculateDataLengthByExtension(torrent, mediaExtensions[mediaType]) }
}).sort((a, b) => { // sort descending on size
return b.size - a.size
})[0]
const bestScore = ['audio', 'video', 'image'].map(mediaType => ({
type: mediaType,
size: calculateDataLengthByExtension(torrent, mediaExtensions[mediaType])
})).sort((a, b) => b.size - a.size)[0] // sort descending on size
if (bestScore.size === 0) {
// Admit defeat, no video, audio or image had a significant presence
@@ -50,9 +45,7 @@ function calculateDataLengthByExtension (torrent, extensions) {
if (files.length === 0) return 0
return files
.map(file => file.length)
.reduce((a, b) => {
return a + b
})
.reduce((a, b) => a + b)
}
/**
@@ -64,16 +57,14 @@ function calculateDataLengthByExtension (torrent, extensions) {
function getLargestFileByExtension (torrent, extensions) {
const files = filterOnExtension(torrent, extensions)
if (files.length === 0) return undefined
return files.reduce((a, b) => {
return a.length > b.length ? a : b
})
return files.reduce((a, b) => a.length > b.length ? a : b)
}
/**
* Filter file on a list extension, can be used to find al image files
* @param torrent Torrent to filter files from
* @param extensions File extensions to filter on
* @returns {number} Array of torrent file objects matching one of the given extensions
* @returns {Array} Array of torrent file objects matching one of the given extensions
*/
function filterOnExtension (torrent, extensions) {
return torrent.files.filter(file => {
@@ -98,7 +89,7 @@ function scoreAudioCoverFile (imgFile) {
spectrogram: -80
}
for (let keyword in relevanceScore) {
for (const keyword in relevanceScore) {
if (fileName === keyword) {
return relevanceScore[keyword]
}
@@ -114,12 +105,10 @@ function torrentPosterFromAudio (torrent, cb) {
if (imageFiles.length === 0) return cb(new Error(msgNoSuitablePoster))
const bestCover = imageFiles.map(file => {
return {
file: file,
score: scoreAudioCoverFile(file)
}
}).reduce((a, b) => {
const bestCover = imageFiles.map(file => ({
file,
score: scoreAudioCoverFile(file)
})).reduce((a, b) => {
if (a.score > b.score) {
return a
}
@@ -165,7 +154,8 @@ function torrentPosterFromVideo (torrent, cb) {
function onSeeked () {
video.removeEventListener('seeked', onSeeked)
const buf = captureFrame(video)
const frame = captureFrame(video)
const buf = frame && frame.image
// unload video element
video.pause()
@@ -188,5 +178,5 @@ function torrentPosterFromImage (torrent, cb) {
function extractPoster (file, cb) {
const extname = path.extname(file.name)
file.getBuffer((err, buf) => { return cb(err, buf, extname) })
file.getBuffer((err, buf) => cb(err, buf, extname))
}

View File

@@ -5,7 +5,7 @@
* actually used because auto-prefixing is disabled with
* `darkBaseTheme.userAgent = false`. Return a fake object.
*/
let Module = require('module')
const Module = require('module')
const _require = Module.prototype.require
Module.prototype.require = function (id) {
if (id === 'inline-style-prefixer') return {}
@@ -14,9 +14,6 @@ Module.prototype.require = function (id) {
console.time('init')
const crashReporter = require('../crash-reporter')
crashReporter.init()
// Perf optimization: Start asynchronously read on config file before all the
// blocking require() calls below.
@@ -39,9 +36,6 @@ const TorrentPlayer = require('./lib/torrent-player')
// Perf optimization: Needed immediately, so do not lazy load it below
const TorrentListController = require('./controllers/torrent-list-controller')
// Required by Material UI -- adds `onTouchTap` event
require('react-tap-event-plugin')()
const App = require('./pages/app')
// Electron apps have two processes: a main process (node) runs first and starts
@@ -77,6 +71,7 @@ function onState (err, _state) {
window.dispatch = dispatch
telemetry.init(state)
sound.init(state)
// Log uncaught JS errors
window.addEventListener(
@@ -101,13 +96,15 @@ function onState (err, _state) {
const SubtitlesController = require('./controllers/subtitles-controller')
return new SubtitlesController(state)
}),
audioTracks: createGetter(() => {
const AudioTracksController = require('./controllers/audio-tracks-controller')
return new AudioTracksController(state)
}),
torrent: createGetter(() => {
const TorrentController = require('./controllers/torrent-controller')
return new TorrentController(state)
}),
torrentList: createGetter(() => {
return new TorrentListController(state)
}),
torrentList: createGetter(() => new TorrentListController(state)),
update: createGetter(() => {
const UpdateController = require('./controllers/update-controller')
return new UpdateController(state)
@@ -127,11 +124,17 @@ function onState (err, _state) {
}
})
// Give global trackers
setGlobalTrackers()
// Restart everything we were torrenting last time the app ran
resumeTorrents()
// Initialize ReactDOM
app = ReactDOM.render(<App state={state} />, document.querySelector('#body'))
ReactDOM.render(
<App state={state} ref={elem => { app = elem }} />,
document.querySelector('#body')
)
// Calling update() updates the UI given the current state
// Do this at least once a second to give every file in every torrentSummary
@@ -150,11 +153,14 @@ function onState (err, _state) {
// ...same thing if you paste a torrent
document.addEventListener('paste', onPaste)
const debouncedFullscreenToggle = debounce(function () {
// Add YouTube style hotkey shortcuts
window.addEventListener('keydown', onKeydown)
const debouncedFullscreenToggle = debounce(() => {
dispatch('toggleFullScreen')
}, 1000, true)
document.addEventListener('wheel', function (event) {
document.addEventListener('wheel', event => {
// ctrlKey detects pinch to zoom, http://crbug.com/289887
if (event.ctrlKey) {
event.preventDefault()
@@ -234,100 +240,112 @@ function updateElectron () {
const dispatchHandlers = {
// Torrent list: creating, deleting, selecting torrents
'openTorrentFile': () => ipcRenderer.send('openTorrentFile'),
'openFiles': () => ipcRenderer.send('openFiles'), /* shows the open file dialog */
'openTorrentAddress': () => { state.modal = { id: 'open-torrent-address-modal' } },
openTorrentFile: () => ipcRenderer.send('openTorrentFile'),
openFiles: () => ipcRenderer.send('openFiles'), /* shows the open file dialog */
openTorrentAddress: () => { state.modal = { id: 'open-torrent-address-modal' } },
'addTorrent': (torrentId) => controllers.torrentList().addTorrent(torrentId),
'showCreateTorrent': (paths) => controllers.torrentList().showCreateTorrent(paths),
'createTorrent': (options) => controllers.torrentList().createTorrent(options),
'toggleTorrent': (infoHash) => controllers.torrentList().toggleTorrent(infoHash),
'pauseAllTorrents': () => controllers.torrentList().pauseAllTorrents(),
'resumeAllTorrents': () => controllers.torrentList().resumeAllTorrents(),
'toggleTorrentFile': (infoHash, index) =>
addTorrent: (torrentId) => controllers.torrentList().addTorrent(torrentId),
showCreateTorrent: (paths) => controllers.torrentList().showCreateTorrent(paths),
createTorrent: (options) => controllers.torrentList().createTorrent(options),
toggleTorrent: (infoHash) => controllers.torrentList().toggleTorrent(infoHash),
pauseAllTorrents: () => controllers.torrentList().pauseAllTorrents(),
resumeAllTorrents: () => controllers.torrentList().resumeAllTorrents(),
toggleTorrentFile: (infoHash, index) =>
controllers.torrentList().toggleTorrentFile(infoHash, index),
'confirmDeleteTorrent': (infoHash, deleteData) =>
confirmDeleteTorrent: (infoHash, deleteData) =>
controllers.torrentList().confirmDeleteTorrent(infoHash, deleteData),
'deleteTorrent': (infoHash, deleteData) =>
deleteTorrent: (infoHash, deleteData) =>
controllers.torrentList().deleteTorrent(infoHash, deleteData),
'toggleSelectTorrent': (infoHash) =>
openTorrentListContextMenu: () => onPaste(),
confirmDeleteAllTorrents: (deleteData) =>
controllers.torrentList().confirmDeleteAllTorrents(deleteData),
deleteAllTorrents: (deleteData) =>
controllers.torrentList().deleteAllTorrents(deleteData),
toggleSelectTorrent: (infoHash) =>
controllers.torrentList().toggleSelectTorrent(infoHash),
'openTorrentContextMenu': (infoHash) =>
openTorrentContextMenu: (infoHash) =>
controllers.torrentList().openTorrentContextMenu(infoHash),
'startTorrentingSummary': (torrentKey) =>
startTorrentingSummary: (torrentKey) =>
controllers.torrentList().startTorrentingSummary(torrentKey),
'saveTorrentFileAs': (torrentKey) =>
saveTorrentFileAs: (torrentKey) =>
controllers.torrentList().saveTorrentFileAs(torrentKey),
'prioritizeTorrent': (infoHash) => controllers.torrentList().prioritizeTorrent(infoHash),
'resumePausedTorrents': () => controllers.torrentList().resumePausedTorrents(),
prioritizeTorrent: (infoHash) => controllers.torrentList().prioritizeTorrent(infoHash),
resumePausedTorrents: () => controllers.torrentList().resumePausedTorrents(),
// Playback
'playFile': (infoHash, index) => controllers.playback().playFile(infoHash, index),
'playPause': () => controllers.playback().playPause(),
'nextTrack': () => controllers.playback().nextTrack(),
'previousTrack': () => controllers.playback().previousTrack(),
'skip': (time) => controllers.playback().skip(time),
'skipTo': (time) => controllers.playback().skipTo(time),
'changePlaybackRate': (dir) => controllers.playback().changePlaybackRate(dir),
'changeVolume': (delta) => controllers.playback().changeVolume(delta),
'setVolume': (vol) => controllers.playback().setVolume(vol),
'openItem': (infoHash, index) => controllers.playback().openItem(infoHash, index),
playFile: (infoHash, index) => controllers.playback().playFile(infoHash, index),
playPause: () => controllers.playback().playPause(),
nextTrack: () => controllers.playback().nextTrack(),
previousTrack: () => controllers.playback().previousTrack(),
skip: (time) => controllers.playback().skip(time),
skipTo: (time) => controllers.playback().skipTo(time),
preview: (x) => controllers.playback().preview(x),
clearPreview: () => controllers.playback().clearPreview(),
changePlaybackRate: (dir) => controllers.playback().changePlaybackRate(dir),
changeVolume: (delta) => controllers.playback().changeVolume(delta),
setVolume: (vol) => controllers.playback().setVolume(vol),
openPath: (infoHash, index) => controllers.playback().openPath(infoHash, index),
// Subtitles
'openSubtitles': () => controllers.subtitles().openSubtitles(),
'selectSubtitle': (index) => controllers.subtitles().selectSubtitle(index),
'toggleSubtitlesMenu': () => controllers.subtitles().toggleSubtitlesMenu(),
'checkForSubtitles': () => controllers.subtitles().checkForSubtitles(),
'addSubtitles': (files, autoSelect) => controllers.subtitles().addSubtitles(files, autoSelect),
openSubtitles: () => controllers.subtitles().openSubtitles(),
selectSubtitle: (index) => controllers.subtitles().selectSubtitle(index),
toggleSubtitlesMenu: () => controllers.subtitles().toggleSubtitlesMenu(),
checkForSubtitles: () => controllers.subtitles().checkForSubtitles(),
addSubtitles: (files, autoSelect) => controllers.subtitles().addSubtitles(files, autoSelect),
// Audio Tracks
selectAudioTrack: (index) => controllers.audioTracks().selectAudioTrack(index),
toggleAudioTracksMenu: () => controllers.audioTracks().toggleAudioTracksMenu(),
// Local media: <video>, <audio>, external players
'mediaStalled': () => controllers.media().mediaStalled(),
'mediaError': (err) => controllers.media().mediaError(err),
'mediaSuccess': () => controllers.media().mediaSuccess(),
'mediaTimeUpdate': () => controllers.media().mediaTimeUpdate(),
'mediaMouseMoved': () => controllers.media().mediaMouseMoved(),
'mediaControlsMouseEnter': () => controllers.media().controlsMouseEnter(),
'mediaControlsMouseLeave': () => controllers.media().controlsMouseLeave(),
'openExternalPlayer': () => controllers.media().openExternalPlayer(),
'externalPlayerNotFound': () => controllers.media().externalPlayerNotFound(),
mediaStalled: () => controllers.media().mediaStalled(),
mediaError: (err) => controllers.media().mediaError(err),
mediaSuccess: () => controllers.media().mediaSuccess(),
mediaTimeUpdate: () => controllers.media().mediaTimeUpdate(),
mediaMouseMoved: () => controllers.media().mediaMouseMoved(),
mediaControlsMouseEnter: () => controllers.media().controlsMouseEnter(),
mediaControlsMouseLeave: () => controllers.media().controlsMouseLeave(),
openExternalPlayer: () => controllers.media().openExternalPlayer(),
externalPlayerNotFound: () => controllers.media().externalPlayerNotFound(),
// Remote casting: Chromecast, Airplay, etc
'toggleCastMenu': (deviceType) => lazyLoadCast().toggleMenu(deviceType),
'selectCastDevice': (index) => lazyLoadCast().selectDevice(index),
'stopCasting': () => lazyLoadCast().stop(),
toggleCastMenu: (deviceType) => lazyLoadCast().toggleMenu(deviceType),
selectCastDevice: (index) => lazyLoadCast().selectDevice(index),
stopCasting: () => lazyLoadCast().stop(),
// Preferences screen
'preferences': () => controllers.prefs().show(),
'updatePreferences': (key, value) => controllers.prefs().update(key, value),
'checkDownloadPath': checkDownloadPath,
'startFolderWatcher': () => controllers.folderWatcher().start(),
'stopFolderWatcher': () => controllers.folderWatcher().stop(),
preferences: () => controllers.prefs().show(),
updatePreferences: (key, value) => controllers.prefs().update(key, value),
checkDownloadPath,
updateGlobalTrackers: (trackers) => setGlobalTrackers(trackers),
startFolderWatcher: () => controllers.folderWatcher().start(),
stopFolderWatcher: () => controllers.folderWatcher().stop(),
// Update (check for new versions on Linux, where there's no auto updater)
'updateAvailable': (version) => controllers.update().updateAvailable(version),
'skipVersion': (version) => controllers.update().skipVersion(version),
updateAvailable: (version) => controllers.update().updateAvailable(version),
skipVersion: (version) => controllers.update().skipVersion(version),
// Navigation between screens (back, forward, ESC, etc)
'exitModal': () => { state.modal = null },
'backToList': backToList,
'escapeBack': escapeBack,
'back': () => state.location.back(),
'forward': () => state.location.forward(),
'cancel': () => state.location.cancel(),
exitModal: () => { state.modal = null },
backToList,
escapeBack,
back: () => state.location.back(),
forward: () => state.location.forward(),
cancel: () => state.location.cancel(),
// Controlling the window
'setDimensions': setDimensions,
'toggleFullScreen': (setTo) => ipcRenderer.send('toggleFullScreen', setTo),
'setTitle': (title) => { state.window.title = title },
'resetTitle': () => { state.window.title = config.APP_WINDOW_TITLE },
setDimensions,
toggleFullScreen: (setTo) => ipcRenderer.send('toggleFullScreen', setTo),
setTitle: (title) => { state.window.title = title },
resetTitle: () => { state.window.title = config.APP_WINDOW_TITLE },
// Everything else
'onOpen': onOpen,
'error': onError,
'uncaughtError': (proc, err) => telemetry.logUncaughtError(proc, err),
'stateSave': () => State.save(state),
'stateSaveImmediate': () => State.saveImmediate(state),
'update': () => {} // No-op, just trigger an update
onOpen,
error: onError,
uncaughtError: (proc, err) => telemetry.logUncaughtError(proc, err),
stateSave: () => State.save(state),
stateSaveImmediate: () => State.saveImmediate(state),
update: () => {} // No-op, just trigger an update
}
// Events from the UI never modify state directly. Instead they call dispatch()
@@ -359,7 +377,7 @@ function setupIpc () {
ipcRenderer.on('windowBoundsChanged', onWindowBoundsChanged)
const tc = controllers.torrent()
ipcRenderer.on('wt-infohash', (e, ...args) => tc.torrentInfoHash(...args))
ipcRenderer.on('wt-parsed', (e, ...args) => tc.torrentParsed(...args))
ipcRenderer.on('wt-metadata', (e, ...args) => tc.torrentMetadata(...args))
ipcRenderer.on('wt-done', (e, ...args) => tc.torrentDone(...args))
ipcRenderer.on('wt-done', () => controllers.torrentList().resumePausedTorrents())
@@ -384,7 +402,7 @@ function setupIpc () {
function backToList () {
// Exit any modals and screens with a back button
state.modal = null
state.location.backToFirst(function () {
state.location.backToFirst(() => {
// If we were already on the torrent list, scroll to the top
const contentTag = document.querySelector('.content')
if (contentTag) contentTag.scrollTop = 0
@@ -402,6 +420,10 @@ function escapeBack () {
}
}
function setGlobalTrackers () {
controllers.torrentList().setGlobalTrackers(state.getGlobalTrackers())
}
// Starts all torrents that aren't paused on program startup
function resumeTorrents () {
state.saved.torrents
@@ -457,7 +479,7 @@ function setDimensions (dimensions) {
// Called when the user adds files (.torrent, files to seed, subtitles) to the app
// via any method (drag-drop, drag to app icon, command line)
function onOpen (files) {
if (!Array.isArray(files)) files = [ files ]
if (!Array.isArray(files)) files = [files]
// File API seems to transform "magnet:?foo" in "magnet:///?foo"
// this is a sanitization
@@ -504,12 +526,43 @@ function onError (err) {
const editableHtmlTags = new Set(['input', 'textarea'])
function onPaste (e) {
if (editableHtmlTags.has(e.target.tagName.toLowerCase())) return
if (e && editableHtmlTags.has(e.target.tagName.toLowerCase())) return
controllers.torrentList().addTorrent(electron.clipboard.readText())
update()
}
function onKeydown (e) {
// prevent event fire on user input elements
if (editableHtmlTags.has(e.target.tagName.toLowerCase())) return
const key = e.key
if (key === 'ArrowLeft') {
dispatch('skip', -5)
} else if (key === 'ArrowRight') {
dispatch('skip', 5)
} else if (key === 'ArrowUp') {
dispatch('changeVolume', 0.1)
} else if (key === 'ArrowDown') {
dispatch('changeVolume', -0.1)
} else if (key === 'j') {
dispatch('skip', -10)
} else if (key === 'l') {
dispatch('skip', 10)
} else if (key === 'k') {
dispatch('playPause')
} else if (key === '>') {
dispatch('changePlaybackRate', 1)
} else if (key === '<') {
dispatch('changePlaybackRate', -1)
} else if (key === 'f') {
dispatch('toggleFullScreen')
}
update()
}
function onFocus (e) {
state.window.isFocused = true
state.dock.badge = 0
@@ -522,7 +575,7 @@ function onBlur () {
}
function onVisibilityChange () {
state.window.isVisible = !document.webkitHidden
state.window.isVisible = !document.hidden
}
function onFullscreenChanged (e, isFullScreen) {
@@ -543,7 +596,7 @@ function onWindowBoundsChanged (e, newBounds) {
}
function checkDownloadPath () {
fs.stat(state.saved.prefs.downloadPath, function (err, stat) {
fs.stat(state.saved.prefs.downloadPath, (err, stat) => {
if (err) {
state.downloadPathStatus = 'missing'
return console.error(err)

View File

@@ -12,10 +12,10 @@ const Header = require('../components/header')
const TorrentListPage = require('./torrent-list-page')
const Views = {
'home': createGetter(() => TorrentListPage),
'player': createGetter(() => require('./player-page')),
home: createGetter(() => TorrentListPage),
player: createGetter(() => require('./player-page')),
'create-torrent': createGetter(() => require('./create-torrent-page')),
'preferences': createGetter(() => require('./preferences-page'))
preferences: createGetter(() => require('./preferences-page'))
}
const Modals = {
@@ -24,7 +24,9 @@ const Modals = {
),
'remove-torrent-modal': createGetter(() => require('../components/remove-torrent-modal')),
'update-available-modal': createGetter(() => require('../components/update-available-modal')),
'unsupported-media-modal': createGetter(() => require('../components/unsupported-media-modal'))
'unsupported-media-modal': createGetter(() => require('../components/unsupported-media-modal')),
'delete-all-torrents-modal':
createGetter(() => require('../components/delete-all-torrents-modal'))
}
const fontFamily = process.platform === 'win32'
@@ -84,12 +86,12 @@ class App extends React.Component {
const recentErrors = state.errors.filter((x) => now - x.time < 5000)
const hasErrors = recentErrors.length > 0
const errorElems = recentErrors.map(function (error, i) {
return (<div key={i} className='error'>{error.message}</div>)
})
const errorElems = recentErrors.map((error, i) => <div key={i} className='error'>{error.message}</div>)
return (
<div key='errors'
className={'error-popover ' + (hasErrors ? 'visible' : 'hidden')}>
<div
key='errors'
className={'error-popover ' + (hasErrors ? 'visible' : 'hidden')}
>
<div key='title' className='title'>Error</div>
{errorElems}
</div>

View File

@@ -65,9 +65,9 @@ class CreateTorrentPage extends React.Component {
}
// Create React event handlers only once
this.setIsPrivate = (_, isPrivate) => this.setState({ isPrivate })
this.setComment = (_, comment) => this.setState({ comment })
this.setTrackers = (_, trackers) => this.setState({ trackers })
this.handleSetIsPrivate = (_, isPrivate) => this.setState({ isPrivate })
this.handleSetComment = (_, comment) => this.setState({ comment })
this.handleSetTrackers = (_, trackers) => this.setState({ trackers })
this.handleSubmit = handleSubmit.bind(this)
}
@@ -94,7 +94,8 @@ class CreateTorrentPage extends React.Component {
marginBottom: 10
}}
hideLabel='Hide advanced settings...'
showLabel='Show advanced settings...'>
showLabel='Show advanced settings...'
>
{this.renderAdvanced()}
</ShowMore>
<div className='float-right'>
@@ -104,12 +105,14 @@ class CreateTorrentPage extends React.Component {
style={{
marginRight: 10
}}
onClick={dispatcher('cancel')} />
onClick={dispatcher('cancel')}
/>
<RaisedButton
className='control create-torrent-button'
label='Create Torrent'
primary
onClick={this.handleSubmit} />
onClick={this.handleSubmit}
/>
</div>
</div>
)
@@ -143,7 +146,8 @@ class CreateTorrentPage extends React.Component {
className='torrent-is-private control'
style={{ display: '' }}
checked={this.state.isPrivate}
onCheck={this.setIsPrivate} />
onCheck={this.handleSetIsPrivate}
/>
</div>
<div key='trackers' className='torrent-attribute'>
<label>Trackers:</label>
@@ -155,7 +159,8 @@ class CreateTorrentPage extends React.Component {
rows={2}
rowsMax={10}
value={this.state.trackers}
onChange={this.setTrackers} />
onChange={this.handleSetTrackers}
/>
</div>
<div key='comment' className='torrent-attribute'>
<label>Comment:</label>
@@ -168,7 +173,8 @@ class CreateTorrentPage extends React.Component {
rows={2}
rowsMax={10}
value={this.state.comment}
onChange={this.setComment} />
onChange={this.handleSetComment}
/>
</div>
<div key='files' className='torrent-attribute'>
<label>Files:</label>

View File

@@ -1,12 +1,14 @@
/* globals MediaMetadata */
const React = require('react')
const Bitfield = require('bitfield')
const BitField = require('bitfield').default
const prettyBytes = require('prettier-bytes')
const zeroFill = require('zero-fill')
const TorrentSummary = require('../lib/torrent-summary')
const Playlist = require('../lib/playlist')
const { dispatch, dispatcher } = require('../lib/dispatcher')
const config = require('../../config')
const { calculateEta } = require('../lib/time')
// Shows a streaming video player. Standard features + Chromecast + Airplay
module.exports = class Player extends React.Component {
@@ -20,7 +22,8 @@ module.exports = class Player extends React.Component {
<div
className='player'
onWheel={handleVolumeWheel}
onMouseMove={dispatcher('mediaMouseMoved')}>
onMouseMove={dispatcher('mediaMouseMoved')}
>
{showVideo ? renderMedia(state) : renderCastScreen(state)}
{showControls ? renderPlayerControls(state) : null}
</div>
@@ -34,6 +37,7 @@ module.exports = class Player extends React.Component {
tag.pause()
tag.src = ''
tag.load()
navigator.mediaSession.metadata = null
}
}
@@ -50,6 +54,28 @@ function renderMedia (state) {
// Get the <video> or <audio> tag
const mediaElement = document.querySelector(state.playing.type)
if (mediaElement !== null) {
if (navigator.mediaSession.metadata === null && mediaElement.played.length !== 0) {
navigator.mediaSession.metadata = new MediaMetadata({
title: state.playing.fileName
})
navigator.mediaSession.setActionHandler('pause', () => {
dispatch('playPause')
})
navigator.mediaSession.setActionHandler('play', () => {
dispatch('playPause')
})
if (Playlist.hasNext(state)) {
navigator.mediaSession.setActionHandler('nexttrack', () => {
dispatch('nextTrack')
})
}
if (Playlist.hasPrevious(state)) {
navigator.mediaSession.setActionHandler('previoustrack', () => {
dispatch('previousTrack')
})
}
}
if (state.playing.isPaused && !mediaElement.paused) {
mediaElement.pause()
} else if (!state.playing.isPaused && mediaElement.paused) {
@@ -95,24 +121,31 @@ function renderMedia (state) {
delete file.selectedSubtitle
}
// Switch to selected audio track
const audioTracks = mediaElement.audioTracks || []
for (let j = 0; j < audioTracks.length; j++) {
const isSelectedTrack = j === state.playing.audioTracks.selectedIndex
audioTracks[j].enabled = isSelectedTrack
}
state.playing.volume = mediaElement.volume
}
// Add subtitles to the <video> tag
const trackTags = []
if (state.playing.subtitles.selectedIndex >= 0) {
for (let i = 0; i < state.playing.subtitles.tracks.length; i++) {
const track = state.playing.subtitles.tracks[i]
state.playing.subtitles.tracks.forEach((track, i) => {
const isSelected = state.playing.subtitles.selectedIndex === i
trackTags.push(
<track
key={i}
default={isSelected ? 'default' : ''}
default={isSelected}
label={track.label}
type='subtitles'
src={track.buffer} />
kind='subtitles'
src={track.buffer}
/>
)
}
})
}
// Create the <audio> or <video> tag
@@ -121,13 +154,14 @@ function renderMedia (state) {
<MediaTagName
src={Playlist.getCurrentLocalURL(state)}
onDoubleClick={dispatcher('toggleFullScreen')}
onClick={dispatcher('playPause')}
onLoadedMetadata={onLoadedMetadata}
onEnded={onEnded}
onStalled={dispatcher('mediaStalled')}
onError={dispatcher('mediaError')}
onTimeUpdate={dispatcher('mediaTimeUpdate')}
onEncrypted={dispatcher('mediaEncrypted')}
onCanPlay={onCanPlay}>
>
{trackTags}
</MediaTagName>
)
@@ -137,24 +171,60 @@ function renderMedia (state) {
<div
key='letterbox'
className='letterbox'
onMouseMove={dispatcher('mediaMouseMoved')}>
onMouseMove={dispatcher('mediaMouseMoved')}
>
{mediaTag}
{renderOverlay(state)}
</div>
)
// As soon as we know the video dimensions, resize the window
function onLoadedMetadata (e) {
if (state.playing.type !== 'video') return
const video = e.target
const dimensions = {
width: video.videoWidth,
height: video.videoHeight
const mediaElement = e.target
// check if we can decode video and audio track
if (state.playing.type === 'video') {
if (mediaElement.videoTracks.length === 0) {
dispatch('mediaError', 'Video codec unsupported')
}
if (mediaElement.audioTracks.length === 0) {
dispatch('mediaError', 'Audio codec unsupported')
}
dispatch('mediaSuccess')
const dimensions = {
width: mediaElement.videoWidth,
height: mediaElement.videoHeight
}
// As soon as we know the video dimensions, resize the window
dispatch('setDimensions', dimensions)
// set audioTracks
const tracks = []
for (let i = 0; i < mediaElement.audioTracks.length; i++) {
tracks.push({
label: mediaElement.audioTracks[i].label || `Track ${i + 1}`,
language: mediaElement.audioTracks[i].language
})
}
state.playing.audioTracks.tracks = tracks
state.playing.audioTracks.selectedIndex = 0
}
// check if we can decode audio track
if (state.playing.type === 'audio') {
if (mediaElement.audioTracks.length === 0) {
dispatch('mediaError', 'Audio codec unsupported')
}
dispatch('mediaSuccess')
}
dispatch('setDimensions', dimensions)
}
function onEnded (e) {
function onEnded () {
if (Playlist.hasNext(state)) {
dispatch('nextTrack')
} else {
@@ -163,19 +233,6 @@ function renderMedia (state) {
if (state.window.isFullScreen) dispatch('toggleFullScreen')
}
}
function onCanPlay (e) {
const elem = e.target
if (state.playing.type === 'video' &&
elem.webkitVideoDecodedByteCount === 0) {
dispatch('mediaError', 'Video codec unsupported')
} else if (elem.webkitAudioDecodedByteCount === 0) {
dispatch('mediaError', 'Audio codec unsupported')
} else {
dispatch('mediaSuccess')
elem.play()
}
}
}
function renderOverlay (state) {
@@ -293,7 +350,7 @@ function renderAudioMetadata (state) {
}
elems.push((
<div key='release' className='audio-release'>
<label>Release</label>{ releaseInfo.join(', ') }
<label>Release</label>{releaseInfo.join(', ')}
</div>
))
}
@@ -301,22 +358,26 @@ function renderAudioMetadata (state) {
// Audio metadata: format
const format = []
fileSummary.audioInfo.format = fileSummary.audioInfo.format || ''
if (fileSummary.audioInfo.format.dataformat) {
format.push(fileSummary.audioInfo.format.dataformat)
if (fileSummary.audioInfo.format.container) {
format.push(fileSummary.audioInfo.format.container)
}
if (fileSummary.audioInfo.format.codec &&
fileSummary.audioInfo.format.container !== fileSummary.audioInfo.format.codec) {
format.push(fileSummary.audioInfo.format.codec)
}
if (fileSummary.audioInfo.format.bitrate) {
format.push(Math.round(fileSummary.audioInfo.format.bitrate / 1000) + ' kbps') // 128 kbps
format.push(Math.round(fileSummary.audioInfo.format.bitrate / 1000) + ' kbit/s') // 128 kbit/s
}
if (fileSummary.audioInfo.format.sampleRate) {
format.push(Math.round(fileSummary.audioInfo.format.sampleRate / 100) / 10 + ' kHz') // 44.1 kHz
format.push(Math.round(fileSummary.audioInfo.format.sampleRate / 100) / 10 + ' kHz')
}
if (fileSummary.audioInfo.format.bitsPerSample) {
format.push(fileSummary.audioInfo.format.bitsPerSample + ' bit')
format.push(fileSummary.audioInfo.format.bitsPerSample + '-bit')
}
if (format.length > 0) {
elems.push((
<div key='format' className='audio-format'>
<label>Format</label>{ format.join(', ') }
<label>Format</label>{format.join(', ')}
</div>
))
}
@@ -358,7 +419,7 @@ function renderLoadingSpinner (state) {
<div key='loading' className='media-stalled'>
<div key='loading-spinner' className='loading-spinner' />
<div key='loading-progress' className='loading-status ellipsis'>
<span className='progress'>{fileProgress}%</span> downloaded
<span><span className='progress'>{fileProgress}%</span> downloaded</span>
<span> ↓ {prettyBytes(prog.downloadSpeed || 0)}/s</span>
<span> ↑ {prettyBytes(prog.uploadSpeed || 0)}/s</span>
</div>
@@ -392,22 +453,70 @@ function renderCastScreen (state) {
const isStarting = state.playing.location.endsWith('-pending')
const castName = state.playing.castName
const fileName = state.getPlayingFileSummary().name || ''
let castStatus
if (isCast && isStarting) castStatus = 'Connecting to ' + castName + '...'
else if (isCast && !isStarting) castStatus = 'Connected to ' + castName
else castStatus = ''
const prog = state.getPlayingTorrentSummary().progress || {}
// Show a nice title image, if possible
const style = {
backgroundImage: cssBackgroundImagePoster(state)
}
function renderEta (total, downloaded) {
const missing = (total || 0) - (downloaded || 0)
const downloadSpeed = prog.downloadSpeed || 0
if (downloadSpeed === 0 || missing === 0) return
const etaStr = calculateEta(missing, downloadSpeed)
return (<span>{etaStr}</span>)
}
function renderDownloadProgress () {
if (!prog.files) return
const fileProg = prog.files[state.playing.fileIndex]
const fileProgress = fileProg.numPiecesPresent / fileProg.numPieces
const fileLength = state.getPlayingFileSummary().length
const fileDownloaded = fileProgress * fileLength
const progress = Math.round(100 * fileProgress)
const total = prettyBytes(fileLength)
const completed = prettyBytes(fileDownloaded)
const downloadSpeed = prettyBytes(prog.downloadSpeed || 0)
const uploadSpeed = prettyBytes(prog.uploadSpeed || 0)
let sizes
if (fileProgress < 1) {
sizes = <span> | {completed} / {total}</span>
} else {
sizes = <span> | {completed}</span>
}
return (
<div key='download-progress'>
<span className='progress'>{progress}% downloaded {sizes}</span>
<br />
<span>↓ {downloadSpeed}/s ↑ {uploadSpeed}/s | {prog.numPeers || 0} peer(s)</span>
<br />
{renderEta(fileLength, fileDownloaded)}
</div>
)
}
return (
<div key='cast' className='letterbox' style={style}>
<div className='cast-screen'>
<i className='icon'>{castIcon}</i>
<div key='type' className='cast-type'>{castType}</div>
<div key='status' className='cast-status'>{castStatus}</div>
<div key='name' className='name'>{fileName}</div>
{renderDownloadProgress()}
</div>
</div>
)
@@ -419,12 +528,13 @@ function renderCastOptions (state) {
const { location, devices } = state.devices.castMenu
const player = state.devices[location]
const items = devices.map(function (device, ix) {
const items = devices.map((device, ix) => {
const isSelected = player.device === device
const name = device.name
return (
<li key={ix} onClick={dispatcher('selectCastDevice', ix)}>
<i className='icon'>{isSelected ? 'radio_button_checked' : 'radio_button_unchecked'}</i>
{' '}
{name}
</li>
)
@@ -441,7 +551,7 @@ function renderSubtitleOptions (state) {
const subtitles = state.playing.subtitles
if (!subtitles.tracks.length || !subtitles.showMenu) return
const items = subtitles.tracks.map(function (track, ix) {
const items = subtitles.tracks.map((track, ix) => {
const isSelected = state.playing.subtitles.selectedIndex === ix
return (
<li key={ix} onClick={dispatcher('selectSubtitle', ix)}>
@@ -464,6 +574,27 @@ function renderSubtitleOptions (state) {
)
}
function renderAudioTrackOptions (state) {
const audioTracks = state.playing.audioTracks
if (!audioTracks.tracks.length || !audioTracks.showMenu) return
const items = audioTracks.tracks.map((track, ix) => {
const isSelected = state.playing.audioTracks.selectedIndex === ix
return (
<li key={ix} onClick={dispatcher('selectAudioTrack', ix)}>
<i className='icon'>{'radio_button_' + (isSelected ? 'checked' : 'unchecked')}</i>
{track.label}
</li>
)
})
return (
<ul key='audio-track-options' className='options-list'>
{items}
</ul>
)
}
function renderPlayerControls (state) {
const positionPercent = 100 * state.playing.currentTime / state.playing.duration
const playbackCursorStyle = { left: 'calc(' + positionPercent + '% - 3px)' }
@@ -472,50 +603,71 @@ function renderPlayerControls (state) {
: state.playing.subtitles.selectedIndex >= 0
? 'active'
: ''
const multiAudioClass = state.playing.audioTracks.tracks.length > 1
? 'active'
: 'disabled'
const prevClass = Playlist.hasPrevious(state) ? '' : 'disabled'
const nextClass = Playlist.hasNext(state) ? '' : 'disabled'
const elements = [
renderPreview(state),
<div key='playback-bar' className='playback-bar'>
{renderLoadingBar(state)}
<div
key='cursor'
className='playback-cursor'
style={playbackCursorStyle} />
style={playbackCursorStyle}
/>
<div
key='scrub-bar'
className='scrub-bar'
draggable='true'
onMouseMove={handleScrubPreview}
onMouseOut={clearPreview}
onDragStart={handleDragStart}
onClick={handleScrub}
onDrag={handleScrub} />
onDrag={handleScrub}
/>
</div>,
<i
key='skip-previous'
className={'icon skip-previous float-left ' + prevClass}
onClick={dispatcher('previousTrack')}>
onClick={dispatcher('previousTrack')}
role='button'
aria-label='Previous track'
>
skip_previous
</i>,
<i
key='play'
className='icon play-pause float-left'
onClick={dispatcher('playPause')}>
onClick={dispatcher('playPause')}
role='button'
aria-label={state.playing.isPaused ? 'Play' : 'Pause'}
>
{state.playing.isPaused ? 'play_arrow' : 'pause'}
</i>,
<i
key='skip-next'
className={'icon skip-next float-left ' + nextClass}
onClick={dispatcher('nextTrack')}>
onClick={dispatcher('nextTrack')}
role='button'
aria-label='Next track'
>
skip_next
</i>,
<i
key='fullscreen'
className='icon fullscreen float-right'
onClick={dispatcher('toggleFullScreen')}>
onClick={dispatcher('toggleFullScreen')}
role='button'
aria-label={state.window.isFullScreen ? 'Exit full screen' : 'Enter full screen'}
>
{state.window.isFullScreen ? 'fullscreen_exit' : 'fullscreen'}
</i>
]
@@ -526,9 +678,20 @@ function renderPlayerControls (state) {
<i
key='subtitles'
className={'icon closed-caption float-right ' + captionsClass}
onClick={handleSubtitles}>
onClick={handleSubtitles}
role='button'
aria-label='Closed captions'
>
closed_caption
</i>
), (
<i
key='audio-tracks'
className={'icon multi-audio float-right ' + multiAudioClass}
onClick={handleAudioTracks}
>
library_music
</i>
))
}
@@ -539,11 +702,11 @@ function renderPlayerControls (state) {
// Add the cast buttons. Icons for each cast type, connected/disconnected:
const buttonIcons = {
'chromecast': { true: 'cast_connected', false: 'cast' },
'airplay': { true: 'airplay', false: 'airplay' },
'dlna': { true: 'tv', false: 'tv' }
chromecast: { true: 'cast_connected', false: 'cast' },
airplay: { true: 'airplay', false: 'airplay' },
dlna: { true: 'tv', false: 'tv' }
}
castTypes.forEach(function (castType) {
castTypes.forEach(castType => {
// Do we show this button (eg. the Chromecast button) at all?
const isCasting = state.playing.location.startsWith(castType)
const player = state.devices[castType]
@@ -570,7 +733,8 @@ function renderPlayerControls (state) {
<i
key={castType}
className={'icon device float-right ' + buttonClass}
onClick={buttonHandler}>
onClick={buttonHandler}
>
{buttonIcon}
</i>
))
@@ -579,10 +743,14 @@ function renderPlayerControls (state) {
// Render volume slider
const volume = state.playing.volume
const volumeIcon = 'volume_' + (
volume === 0 ? 'off'
: volume < 0.3 ? 'mute'
: volume < 0.6 ? 'down'
: 'up')
volume === 0
? 'off'
: volume < 0.3
? 'mute'
: volume < 0.6
? 'down'
: 'up'
)
const volumeStyle = {
background: '-webkit-gradient(linear, left top, right top, ' +
'color-stop(' + (volume * 100) + '%, #eee), ' +
@@ -593,7 +761,10 @@ function renderPlayerControls (state) {
<div key='volume' className='volume float-left'>
<i
className='icon volume-icon float-left'
onMouseDown={handleVolumeMute}>
onMouseDown={handleVolumeMute}
role='button'
aria-label='Mute'
>
{volumeIcon}
</i>
<input
@@ -601,7 +772,8 @@ function renderPlayerControls (state) {
type='range' min='0' max='1' step='0.05'
value={volume}
onChange={handleVolumeScrub}
style={volumeStyle} />
style={volumeStyle}
/>
</div>
))
@@ -623,24 +795,31 @@ function renderPlayerControls (state) {
))
}
return (
<div key='controls' className='controls'
onMouseEnter={dispatcher('mediaControlsMouseEnter')}
onMouseLeave={dispatcher('mediaControlsMouseLeave')}>
{elements}
{renderCastOptions(state)}
{renderSubtitleOptions(state)}
</div>
)
const emptyImage = new window.Image(0, 0)
emptyImage.src = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D'
function handleDragStart (e) {
// Prevent the cursor from changing, eg to a green + icon on Mac
if (e.dataTransfer) {
const dt = e.dataTransfer
// Prevent the cursor from changing, eg to a green + icon on Mac
dt.effectAllowed = 'none'
// Prevent ghost image
dt.setDragImage(emptyImage, 0, 0)
}
}
// Handles a scrub hover (preview another position in the video)
function handleScrubPreview (e) {
// Only show for videos
if (!e.clientX || state.playing.type !== 'video') return
dispatch('mediaMouseMoved')
dispatch('preview', e.clientX)
}
function clearPreview () {
if (state.playing.type !== 'video') return
dispatch('clearPreview')
}
// Handles a click or drag to scrub (jump to another position in the video)
function handleScrub (e) {
if (!e.clientX) return
@@ -652,7 +831,7 @@ function renderPlayerControls (state) {
}
// Handles volume muting and Unmuting
function handleVolumeMute (e) {
function handleVolumeMute () {
if (state.playing.volume === 0.0) {
dispatch('setVolume', 1.0)
} else {
@@ -673,6 +852,73 @@ function renderPlayerControls (state) {
dispatch('toggleSubtitlesMenu')
}
}
function handleAudioTracks () {
dispatch('toggleAudioTracksMenu')
}
return (
<div
key='controls' className='controls'
onMouseEnter={dispatcher('mediaControlsMouseEnter')}
onMouseLeave={dispatcher('mediaControlsMouseLeave')}
>
{elements}
{renderCastOptions(state)}
{renderSubtitleOptions(state)}
{renderAudioTrackOptions(state)}
</div>
)
}
function renderPreview (state) {
const { previewXCoord = null } = state.playing
// Calculate time from x-coord as fraction of track width
const windowWidth = document.querySelector('body').clientWidth
const fraction = previewXCoord / windowWidth
const time = fraction * state.playing.duration /* seconds */
const height = 70
let width = 0
const previewEl = document.querySelector('video#preview')
if (previewEl !== null && previewXCoord !== null) {
previewEl.currentTime = time
// Auto adjust width to maintain video aspect ratio
width = Math.floor((previewEl.videoWidth / previewEl.videoHeight) * height)
}
// Center preview window on mouse cursor,
// while avoiding falling off the left or right edges
const xPos = Math.min(Math.max(previewXCoord - (width / 2), 5), windowWidth - width - 5)
return (
<div
key='preview' style={{
position: 'absolute',
bottom: 50,
left: xPos,
display: previewXCoord == null && 'none' // Hide preview when XCoord unset
}}
>
<div style={{ width, height, backgroundColor: 'black' }}>
<video
src={Playlist.getCurrentLocalURL(state)}
id='preview'
style={{ border: '1px solid lightgrey', borderRadius: 2 }}
/>
</div>
<p
style={{
textAlign: 'center', margin: 5, textShadow: '0 0 2px rgba(0,0,0,.5)', color: '#eee'
}}
>
{formatTime(time, state.playing.duration)}
</p>
</div>
)
}
// Renders the loading bar. Shows which parts of the torrent are loaded, which
@@ -694,7 +940,7 @@ function renderLoadingBar (state) {
const parts = []
let lastPiecePresent = false
for (let i = fileProg.startPiece; i <= fileProg.endPiece; i++) {
const partPresent = Bitfield.prototype.get.call(prog.bitfield, i)
const partPresent = BitField.prototype.get.call(prog.bitfield, i)
if (partPresent && !lastPiecePresent) {
parts.push({ start: i - fileProg.startPiece, count: 1 })
} else if (partPresent) {
@@ -704,7 +950,7 @@ function renderLoadingBar (state) {
}
// Output some bars to show which parts of the file are loaded
const loadingBarElems = parts.map(function (part, i) {
const loadingBarElems = parts.map((part, i) => {
const style = {
left: (100 * part.start / fileProg.numPieces) + '%',
width: (100 * part.count / fileProg.numPieces) + '%'
@@ -734,14 +980,14 @@ function formatTime (time, total) {
return '0:00'
}
let totalHours = Math.floor(total / 3600)
let totalMinutes = Math.floor(total % 3600 / 60)
let hours = Math.floor(time / 3600)
const totalHours = Math.floor(total / 3600)
const totalMinutes = Math.floor(total / 60)
const hours = Math.floor(time / 3600)
let minutes = Math.floor(time % 3600 / 60)
if (totalMinutes > 9) {
minutes = zeroFill(2, minutes)
if (totalMinutes > 9 && minutes < 10) {
minutes = '0' + minutes
}
let seconds = zeroFill(2, Math.floor(time % 60))
const seconds = `0${Math.floor(time % 60)}`.slice(-2)
return (totalHours > 0 ? hours + ':' : '') + minutes + ':' + seconds
}

View File

@@ -1,9 +1,10 @@
const path = require('path')
const React = require('react')
const PropTypes = require('prop-types')
const colors = require('material-ui/styles/colors')
const Checkbox = require('material-ui/Checkbox').default
const RaisedButton = require('material-ui/RaisedButton').default
const TextField = require('material-ui/TextField').default
const Heading = require('../components/heading')
const PathSelector = require('../components/path-selector')
@@ -25,6 +26,18 @@ class PreferencesPage extends React.Component {
this.handleStartupChange =
this.handleStartupChange.bind(this)
this.handleSoundNotificationsChange =
this.handleSoundNotificationsChange.bind(this)
this.handleSetGlobalTrackers =
this.handleSetGlobalTrackers.bind(this)
const globalTrackers = this.props.state.getGlobalTrackers().join('\n')
this.state = {
globalTrackers
}
}
downloadPathSelector () {
@@ -33,11 +46,12 @@ class PreferencesPage extends React.Component {
<PathSelector
dialog={{
title: 'Select download directory',
properties: [ 'openDirectory' ]
properties: ['openDirectory']
}}
onChange={this.handleDownloadPathChange}
title='Download location'
value={this.props.state.saved.prefs.downloadPath} />
value={this.props.state.saved.prefs.downloadPath}
/>
</Preference>
)
}
@@ -52,8 +66,9 @@ class PreferencesPage extends React.Component {
<Checkbox
className='control'
checked={!this.props.state.saved.prefs.openExternalPlayer}
label={'Play torrent media files using WebTorrent'}
onCheck={this.handleOpenExternalPlayerChange} />
label='Play torrent media files using WebTorrent'
onCheck={this.handleOpenExternalPlayerChange}
/>
</Preference>
)
}
@@ -68,7 +83,7 @@ class PreferencesPage extends React.Component {
<Checkbox
className='control'
checked={this.props.state.saved.prefs.highestPlaybackPriority}
label={'Highest Playback Priority'}
label='Highest Playback Priority'
onCheck={this.handleHighestPlaybackPriorityChange}
/>
<p>Pauses all active torrents to allow playback to use all of the available bandwidth.</p>
@@ -94,12 +109,12 @@ class PreferencesPage extends React.Component {
<PathSelector
dialog={{
title: 'Select media player app',
properties: [ 'openFile' ]
properties: ['openFile']
}}
displayValue={playerName}
onChange={this.handleExternalPlayerPathChange}
title='External player'
value={playerPath ? path.dirname(playerPath) : null} />
value={playerPath}
/>
</Preference>
)
}
@@ -114,7 +129,7 @@ class PreferencesPage extends React.Component {
<Checkbox
className='control'
checked={this.props.state.saved.prefs.autoAddTorrents}
label={'Watch for new .torrent files and add them immediately'}
label='Watch for new .torrent files and add them immediately'
onCheck={(e, value) => { this.handleAutoAddTorrentsChange(e, value) }}
/>
</Preference>
@@ -132,11 +147,11 @@ class PreferencesPage extends React.Component {
dispatch('updatePreferences', 'autoAddTorrents', isChecked)
if (isChecked) {
dispatch('startFolderWatcher', null)
dispatch('startFolderWatcher')
return
}
dispatch('stopFolderWatcher', null)
dispatch('stopFolderWatcher')
}
torrentsFolderPathSelector () {
@@ -147,17 +162,17 @@ class PreferencesPage extends React.Component {
<PathSelector
dialog={{
title: 'Select folder to watch for new torrents',
properties: [ 'openDirectory' ]
properties: ['openDirectory']
}}
displayValue={torrentsFolderPath || ''}
onChange={this.handletorrentsFolderPathChange}
onChange={this.handleTorrentsFolderPathChange}
title='Folder to watch'
value={torrentsFolderPath ? path.dirname(torrentsFolderPath) : null} />
value={torrentsFolderPath}
/>
</Preference>
)
}
handletorrentsFolderPathChange (filePath) {
handleTorrentsFolderPathChange (filePath) {
dispatch('updatePreferences', 'torrentsFolderPath', filePath)
}
@@ -176,7 +191,8 @@ class PreferencesPage extends React.Component {
<RaisedButton
className='control'
onClick={this.handleSetDefaultApp}
label='Make WebTorrent the default' />
label='Make WebTorrent the default'
/>
</Preference>
)
}
@@ -185,29 +201,77 @@ class PreferencesPage extends React.Component {
dispatch('updatePreferences', 'startup', isChecked)
}
setStartupSection () {
setStartupCheckbox () {
if (config.IS_PORTABLE) {
return
}
return (
<PreferencesSection title='Startup'>
<Preference>
<Checkbox
className='control'
checked={this.props.state.saved.prefs.startup}
label={'Open WebTorrent on startup.'}
onCheck={this.handleStartupChange}
/>
</Preference>
</PreferencesSection>
<Preference>
<Checkbox
className='control'
checked={this.props.state.saved.prefs.startup}
label='Open WebTorrent on startup'
onCheck={this.handleStartupChange}
/>
</Preference>
)
}
soundNotificationsCheckbox () {
return (
<Preference>
<Checkbox
className='control'
checked={this.props.state.saved.prefs.soundNotifications}
label='Enable sounds'
onCheck={this.handleSoundNotificationsChange}
/>
</Preference>
)
}
handleSoundNotificationsChange (e, isChecked) {
dispatch('updatePreferences', 'soundNotifications', isChecked)
}
handleSetDefaultApp () {
dispatch('updatePreferences', 'isFileHandler', true)
}
setGlobalTrackers () {
// Align the text fields
const textFieldStyle = { width: '100%' }
const textareaStyle = { margin: 0 }
return (
<Preference>
<TextField
className='torrent-trackers control'
style={textFieldStyle}
textareaStyle={textareaStyle}
multiLine
rows={2}
rowsMax={10}
value={this.state.globalTrackers}
onChange={this.handleSetGlobalTrackers}
/>
</Preference>
)
}
handleSetGlobalTrackers (e, globalTrackers) {
this.setState({ globalTrackers })
const announceList = globalTrackers
.split('\n')
.map((s) => s.trim())
.filter((s) => s !== '')
dispatch('updatePreferences', 'globalTrackers', announceList)
dispatch('updateGlobalTrackers', announceList)
}
render () {
const style = {
color: colors.grey400,
@@ -229,7 +293,13 @@ class PreferencesPage extends React.Component {
<PreferencesSection title='Default torrent app'>
{this.setDefaultAppButton()}
</PreferencesSection>
{this.setStartupSection()}
<PreferencesSection title='General'>
{this.setStartupCheckbox()}
{this.soundNotificationsCheckbox()}
</PreferencesSection>
<PreferencesSection title='Trackers'>
{this.setGlobalTrackers()}
</PreferencesSection>
</div>
)
}
@@ -238,7 +308,7 @@ class PreferencesPage extends React.Component {
class PreferencesSection extends React.Component {
static get propTypes () {
return {
title: React.PropTypes.string
title: PropTypes.string
}
}

View File

@@ -7,6 +7,7 @@ const LinearProgress = require('material-ui/LinearProgress').default
const TorrentSummary = require('../lib/torrent-summary')
const TorrentPlayer = require('../lib/torrent-player')
const { dispatcher } = require('../lib/dispatcher')
const { calculateEta } = require('../lib/time')
module.exports = class TorrentList extends React.Component {
render () {
@@ -35,7 +36,11 @@ module.exports = class TorrentList extends React.Component {
)
return (
<div key='torrent-list' className='torrent-list'>
<div
key='torrent-list'
className='torrent-list'
onContextMenu={dispatcher('openTorrentListContextMenu')}
>
{contents}
</div>
)
@@ -67,7 +72,8 @@ module.exports = class TorrentList extends React.Component {
style={style}
className={classes.join(' ')}
onContextMenu={infoHash && dispatcher('openTorrentContextMenu', infoHash)}
onClick={infoHash && dispatcher('toggleSelectTorrent', infoHash)}>
onClick={infoHash && dispatcher('toggleSelectTorrent', infoHash)}
>
{this.renderTorrentMetadata(torrentSummary)}
{infoHash ? this.renderTorrentButtons(torrentSummary) : null}
{isSelected ? this.renderTorrentDetails(torrentSummary) : null}
@@ -130,7 +136,8 @@ module.exports = class TorrentList extends React.Component {
}}
checked={isActive}
onClick={stopPropagation}
onCheck={dispatcher('toggleTorrent', infoHash)} />
onCheck={dispatcher('toggleTorrent', infoHash)}
/>
)
}
@@ -147,7 +154,7 @@ module.exports = class TorrentList extends React.Component {
}
}
return (
<div style={styles.wrapper}>
<div key='progress-bar' style={styles.wrapper}>
<LinearProgress style={styles.progress} mode='determinate' value={progress} />
</div>
)
@@ -189,18 +196,9 @@ module.exports = class TorrentList extends React.Component {
const downloadSpeed = prog.downloadSpeed
if (downloadSpeed === 0 || missing === 0) return
const rawEta = missing / downloadSpeed
const hours = Math.floor(rawEta / 3600) % 24
const minutes = Math.floor(rawEta / 60) % 60
const seconds = Math.floor(rawEta % 60)
const etaStr = calculateEta(missing, downloadSpeed)
// Only display hours and minutes if they are greater than 0 but always
// display minutes if hours is being displayed
const hoursStr = hours ? hours + 'h' : ''
const minutesStr = (hours || minutes) ? minutes + 'm' : ''
const secondsStr = seconds + 's'
return (<span>{hoursStr} {minutesStr} {secondsStr} remaining</span>)
return (<span key='eta'>{etaStr}</span>)
}
function renderTorrentStatus () {
@@ -210,7 +208,9 @@ module.exports = class TorrentList extends React.Component {
else if (torrentSummary.progress.progress === 1) status = 'Not seeding'
else status = 'Paused'
} else if (torrentSummary.status === 'downloading') {
status = 'Downloading'
if (!torrentSummary.progress) status = ''
else if (!torrentSummary.progress.ready) status = 'Verifying'
else status = 'Downloading'
} else if (torrentSummary.status === 'seeding') {
status = 'Seeding'
} else { // torrentSummary.status is 'new' or something unexpected
@@ -232,8 +232,9 @@ module.exports = class TorrentList extends React.Component {
<i
key='play-button'
title='Start streaming'
className={'icon play'}
onClick={dispatcher('playFile', infoHash)}>
className='icon play'
onClick={dispatcher('playFile', infoHash)}
>
play_circle_outline
</i>
)
@@ -246,7 +247,8 @@ module.exports = class TorrentList extends React.Component {
key='delete-button'
className='icon delete'
title='Remove torrent'
onClick={dispatcher('confirmDeleteTorrent', infoHash, false)}>
onClick={dispatcher('confirmDeleteTorrent', infoHash, false)}
>
close
</i>
</div>
@@ -278,10 +280,17 @@ module.exports = class TorrentList extends React.Component {
)
} else {
// We do know the files. List them and show download stats for each one
const fileRows = torrentSummary.files
const sortByName = this.props.state.saved.prefs.sortByName
const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' })
let fileRows = torrentSummary.files
.filter((file) => !file.path.includes('/.____padding_file/'))
.map((file, index) => ({ file, index }))
.map((object) => this.renderFileRow(torrentSummary, object.file, object.index))
if (sortByName) {
fileRows = fileRows.sort((a, b) => collator.compare(a.file.name, b.file.name))
}
fileRows = fileRows.map((obj) => this.renderFileRow(torrentSummary, obj.file, obj.index))
filesElement = (
<div key='files' className='files'>
@@ -312,7 +321,7 @@ module.exports = class TorrentList extends React.Component {
torrentSummary.progress.files[index]) {
const fileProg = torrentSummary.progress.files[index]
isDone = fileProg.numPiecesPresent === fileProg.numPieces
progress = Math.round(100 * fileProg.numPiecesPresent / fileProg.numPieces) + '%'
progress = Math.floor(100 * fileProg.numPiecesPresent / fileProg.numPieces) + '%'
}
// Second, for media files where we saved our position, show how far we got
@@ -333,7 +342,7 @@ module.exports = class TorrentList extends React.Component {
} else {
icon = 'description' /* file icon, opens in OS default app */
handleClick = isDone
? dispatcher('openItem', infoHash, index)
? dispatcher('openPath', infoHash, index)
: (e) => e.stopPropagation() // noop if file is not ready
}
// TODO: add a css 'disabled' class to indicate that a file cannot be opened/streamed
@@ -355,8 +364,10 @@ module.exports = class TorrentList extends React.Component {
<td className={'col-size ' + rowClass}>
{prettyBytes(file.length)}
</td>
<td className='col-select'
onClick={dispatcher('toggleTorrentFile', infoHash, index)}>
<td
className='col-select'
onClick={dispatcher('toggleTorrentFile', infoHash, index)}
>
<i className='icon deselect-file'>{isSelected ? 'close' : 'add'}</i>
</td>
</tr>
@@ -370,16 +381,16 @@ module.exports = class TorrentList extends React.Component {
return (
<div key='radial-progress' className={'radial-progress ' + cssClass}>
<div key='circle' className='circle'>
<div key='mask-full' className='mask full' style={transformFill}>
<div key='fill' className='fill' style={transformFill} />
<div className='circle'>
<div className='mask full' style={transformFill}>
<div className='fill' style={transformFill} />
</div>
<div key='mask-half' className='mask half'>
<div key='fill' className='fill' style={transformFill} />
<div key='fill-fix' className='fill fix' style={transformFix} />
<div className='mask half'>
<div className='fill' style={transformFill} />
<div className='fill fix' style={transformFix} />
</div>
</div>
<div key='inset' className='inset' />
<div className='inset' />
</div>
)
}
@@ -393,7 +404,7 @@ function getErrorMessage (torrentSummary) {
const err = torrentSummary.error
if (err === 'path-missing') {
return (
<span>
<span key='path-missing'>
Path missing.<br />
Fix and restart the app, or delete the torrent.
</span>

View File

@@ -3,33 +3,18 @@
console.time('init')
const crypto = require('crypto')
const deepEqual = require('deep-equal')
const defaultAnnounceList = require('create-torrent').announceList
const electron = require('electron')
const util = require('util')
const { ipcRenderer } = require('electron')
const fs = require('fs')
const mkdirp = require('mkdirp')
const mm = require('music-metadata')
const networkAddress = require('network-address')
const path = require('path')
const WebTorrent = require('webtorrent')
const zeroFill = require('zero-fill')
const crashReporter = require('../crash-reporter')
const config = require('../config')
const { TorrentKeyNotFoundError } = require('./lib/errors')
const torrentPoster = require('./lib/torrent-poster')
// Report when the process crashes
crashReporter.init()
// Send & receive messages from the main window
const ipc = electron.ipcRenderer
// Force use of webtorrent trackers on all torrents
global.WEBTORRENT_ANNOUNCE = defaultAnnounceList
.map((arr) => arr[0])
.filter((url) => url.indexOf('wss://') === 0 || url.indexOf('ws://') === 0)
/**
* WebTorrent version.
*/
@@ -41,10 +26,9 @@ const VERSION = require('../../package.json').version
* '0.16.1' -> '0016'
* '1.2.5' -> '0102'
*/
const VERSION_STR = VERSION.match(/([0-9]+)/g)
.slice(0, 2)
.map((v) => zeroFill(2, v))
.join('')
const VERSION_STR = VERSION
.replace(/\d*./g, v => `0${v % 100}`.slice(-2))
.slice(0, 4)
/**
* Version prefix string (used in peer ID). WebTorrent uses the Azureus-style
@@ -75,29 +59,31 @@ init()
function init () {
listenToClientEvents()
ipc.on('wt-start-torrenting', (e, torrentKey, torrentID, path, fileModtimes, selections) =>
ipcRenderer.on('wt-set-global-trackers', (e, globalTrackers) =>
setGlobalTrackers(globalTrackers))
ipcRenderer.on('wt-start-torrenting', (e, torrentKey, torrentID, path, fileModtimes, selections) =>
startTorrenting(torrentKey, torrentID, path, fileModtimes, selections))
ipc.on('wt-stop-torrenting', (e, infoHash) =>
ipcRenderer.on('wt-stop-torrenting', (e, infoHash) =>
stopTorrenting(infoHash))
ipc.on('wt-create-torrent', (e, torrentKey, options) =>
ipcRenderer.on('wt-create-torrent', (e, torrentKey, options) =>
createTorrent(torrentKey, options))
ipc.on('wt-save-torrent-file', (e, torrentKey) =>
ipcRenderer.on('wt-save-torrent-file', (e, torrentKey) =>
saveTorrentFile(torrentKey))
ipc.on('wt-generate-torrent-poster', (e, torrentKey) =>
ipcRenderer.on('wt-generate-torrent-poster', (e, torrentKey) =>
generateTorrentPoster(torrentKey))
ipc.on('wt-get-audio-metadata', (e, infoHash, index) =>
ipcRenderer.on('wt-get-audio-metadata', (e, infoHash, index) =>
getAudioMetadata(infoHash, index))
ipc.on('wt-start-server', (e, infoHash) =>
ipcRenderer.on('wt-start-server', (e, infoHash) =>
startServer(infoHash))
ipc.on('wt-stop-server', (e) =>
ipcRenderer.on('wt-stop-server', () =>
stopServer())
ipc.on('wt-select-files', (e, infoHash, selections) =>
ipcRenderer.on('wt-select-files', (e, infoHash, selections) =>
selectFiles(infoHash, selections))
ipc.send('ipcReadyWebTorrent')
ipcRenderer.send('ipcReadyWebTorrent')
window.addEventListener('error', (e) =>
ipc.send('wt-uncaught-error', { message: e.error.message, stack: e.error.stack }),
ipcRenderer.send('wt-uncaught-error', { message: e.error.message, stack: e.error.stack }),
true)
setInterval(updateTorrentProgress, 1000)
@@ -105,8 +91,13 @@ function init () {
}
function listenToClientEvents () {
client.on('warning', (err) => ipc.send('wt-warning', null, err.message))
client.on('error', (err) => ipc.send('wt-error', null, err.message))
client.on('warning', (err) => ipcRenderer.send('wt-warning', null, err.message))
client.on('error', (err) => ipcRenderer.send('wt-error', null, err.message))
}
// Sets the default trackers
function setGlobalTrackers (globalTrackers) {
globalThis.WEBTORRENT_ANNOUNCE = globalTrackers
}
// Starts a given TorrentID, which can be an infohash, magnet URI, etc.
@@ -115,8 +106,8 @@ function startTorrenting (torrentKey, torrentID, path, fileModtimes, selections)
console.log('starting torrent %s: %s', torrentKey, torrentID)
const torrent = client.add(torrentID, {
path: path,
fileModtimes: fileModtimes
path,
fileModtimes
})
torrent.key = torrentKey
@@ -140,44 +131,44 @@ function createTorrent (torrentKey, options) {
const torrent = client.seed(paths, options)
torrent.key = torrentKey
addTorrentEvents(torrent)
ipc.send('wt-new-torrent')
ipcRenderer.send('wt-new-torrent')
}
function addTorrentEvents (torrent) {
torrent.on('warning', (err) =>
ipc.send('wt-warning', torrent.key, err.message))
ipcRenderer.send('wt-warning', torrent.key, err.message))
torrent.on('error', (err) =>
ipc.send('wt-error', torrent.key, err.message))
ipcRenderer.send('wt-error', torrent.key, err.message))
torrent.on('infoHash', () =>
ipc.send('wt-infohash', torrent.key, torrent.infoHash))
ipcRenderer.send('wt-parsed', torrent.key, torrent.infoHash, torrent.magnetURI))
torrent.on('metadata', torrentMetadata)
torrent.on('ready', torrentReady)
torrent.on('done', torrentDone)
function torrentMetadata () {
const info = getTorrentInfo(torrent)
ipc.send('wt-metadata', torrent.key, info)
ipcRenderer.send('wt-metadata', torrent.key, info)
updateTorrentProgress()
}
function torrentReady () {
const info = getTorrentInfo(torrent)
ipc.send('wt-ready', torrent.key, info)
ipc.send('wt-ready-' + torrent.infoHash, torrent.key, info)
ipcRenderer.send('wt-ready', torrent.key, info)
ipcRenderer.send('wt-ready-' + torrent.infoHash, torrent.key, info)
updateTorrentProgress()
}
function torrentDone () {
const info = getTorrentInfo(torrent)
ipc.send('wt-done', torrent.key, info)
ipcRenderer.send('wt-done', torrent.key, info)
updateTorrentProgress()
torrent.getFileModtimes(function (err, fileModtimes) {
torrent.getFileModtimes((err, fileModtimes) => {
if (err) return onError(err)
ipc.send('wt-file-modtimes', torrent.key, fileModtimes)
ipcRenderer.send('wt-file-modtimes', torrent.key, fileModtimes)
})
}
}
@@ -210,19 +201,19 @@ function saveTorrentFile (torrentKey) {
const torrent = getTorrent(torrentKey)
const torrentPath = path.join(config.TORRENT_PATH, torrent.infoHash + '.torrent')
fs.access(torrentPath, fs.constants.R_OK, function (err) {
fs.access(torrentPath, fs.constants.R_OK, err => {
const fileName = torrent.infoHash + '.torrent'
if (!err) {
// We've already saved the file
return ipc.send('wt-file-saved', torrentKey, fileName)
return ipcRenderer.send('wt-file-saved', torrentKey, fileName)
}
// Otherwise, save the .torrent file, under the app config folder
mkdirp(config.TORRENT_PATH, function (_) {
fs.writeFile(torrentPath, torrent.torrentFile, function (err) {
fs.mkdir(config.TORRENT_PATH, { recursive: true }, _ => {
fs.writeFile(torrentPath, torrent.torrentFile, err => {
if (err) return console.log('error saving torrent file %s: %o', torrentPath, err)
console.log('saved torrent file %s', torrentPath)
return ipc.send('wt-file-saved', torrentKey, fileName)
return ipcRenderer.send('wt-file-saved', torrentKey, fileName)
})
})
})
@@ -232,17 +223,17 @@ function saveTorrentFile (torrentKey) {
// Auto chooses either a frame from a video file, an image, etc
function generateTorrentPoster (torrentKey) {
const torrent = getTorrent(torrentKey)
torrentPoster(torrent, function (err, buf, extension) {
torrentPoster(torrent, (err, buf, extension) => {
if (err) return console.log('error generating poster: %o', err)
// save it for next time
mkdirp(config.POSTER_PATH, function (err) {
fs.mkdir(config.POSTER_PATH, { recursive: true }, err => {
if (err) return console.log('error creating poster dir: %o', err)
const posterFileName = torrent.infoHash + extension
const posterFilePath = path.join(config.POSTER_PATH, posterFileName)
fs.writeFile(posterFilePath, buf, function (err) {
fs.writeFile(posterFilePath, buf, err => {
if (err) return console.log('error saving poster: %o', err)
// show the poster
ipc.send('wt-poster', torrentKey, posterFileName)
ipcRenderer.send('wt-poster', torrentKey, posterFileName)
})
})
})
@@ -251,25 +242,23 @@ function generateTorrentPoster (torrentKey) {
function updateTorrentProgress () {
const progress = getTorrentProgress()
// TODO: diff torrent-by-torrent, not once for the whole update
if (prevProgress && deepEqual(progress, prevProgress, { strict: true })) {
if (prevProgress && util.isDeepStrictEqual(progress, prevProgress)) {
return /* don't send heavy object if it hasn't changed */
}
ipc.send('wt-progress', progress)
ipcRenderer.send('wt-progress', progress)
prevProgress = progress
}
function getTorrentProgress () {
// First, track overall progress
const progress = client.progress
const hasActiveTorrents = client.torrents.some(function (torrent) {
return torrent.progress !== 1
})
const hasActiveTorrents = client.torrents.some(torrent => torrent.progress !== 1)
// Track progress for every file in each torrent
// TODO: ideally this would be tracked by WebTorrent, which could do it
// more efficiently than looping over torrent.bitfield
const torrentProg = client.torrents.map(function (torrent) {
const fileProg = torrent.files && torrent.files.map(function (file, index) {
const torrentProg = client.torrents.map(torrent => {
const fileProg = torrent.files && torrent.files.map(file => {
const numPieces = file._endPiece - file._startPiece + 1
let numPiecesPresent = 0
for (let piece = file._startPiece; piece <= file._endPiece; piece++) {
@@ -309,12 +298,12 @@ function startServer (infoHash) {
else torrent.once('ready', () => startServerFromReadyTorrent(torrent))
}
function startServerFromReadyTorrent (torrent, cb) {
function startServerFromReadyTorrent (torrent) {
if (server) return
// start the streaming torrent-to-http server
server = torrent.createServer()
server.listen(0, function () {
server.listen(0, () => {
const port = server.address().port
const urlSuffix = ':' + port
const info = {
@@ -324,8 +313,8 @@ function startServerFromReadyTorrent (torrent, cb) {
networkAddress: networkAddress()
}
ipc.send('wt-server-running', info)
ipc.send('wt-server-' + torrent.infoHash, info)
ipcRenderer.send('wt-server-running', info)
ipcRenderer.send('wt-server-' + torrent.infoHash, info)
})
}
@@ -343,26 +332,38 @@ function getAudioMetadata (infoHash, index) {
// Set initial matadata to display the filename first.
const metadata = { title: file.name }
ipc.send('wt-audio-metadata', infoHash, index, metadata)
ipcRenderer.send('wt-audio-metadata', infoHash, index, metadata)
const options = { native: false,
const options = {
native: false,
skipCovers: true,
fileSize: file.length,
observer: event => {
ipc.send('wt-audio-metadata', infoHash, index, event.metadata)
} }
const onMetaData = file.done
observer: () => {
ipcRenderer.send('wt-audio-metadata', infoHash, index, {
common: metadata.common,
format: metadata.format
})
}
}
const onMetadata = file.done
// If completed; use direct file access
? mm.parseFile(path.join(torrent.path, file.path), options)
// otherwise stream
: mm.parseStream(file.createReadStream(), file.name, options)
onMetaData
.then(() => {
console.log(`metadata for file='${file.name}' completed.`)
}).catch(function (err) {
return console.log('error getting audio metadata for ' + infoHash + ':' + index, err)
})
onMetadata
.then(
metadata => {
ipcRenderer.send('wt-audio-metadata', infoHash, index, metadata)
console.log(`metadata for file='${file.name}' completed.`)
},
err => {
console.log(
`error getting audio metadata for ${infoHash}:${index}`,
err
)
}
)
}
function selectFiles (torrentOrInfoHash, selections) {
@@ -382,7 +383,7 @@ function selectFiles (torrentOrInfoHash, selections) {
// selection with individual selections for each file, so we can
// select/deselect files later on
if (!selections) {
selections = torrent.files.map((x) => true)
selections = new Array(torrent.files.length).fill(true)
}
// Selections specified incorrectly?
@@ -395,15 +396,15 @@ function selectFiles (torrentOrInfoHash, selections) {
torrent.deselect(0, torrent.pieces.length - 1, false)
// Add selections (individual files)
for (let i = 0; i < selections.length; i++) {
selections.forEach((selection, i) => {
const file = torrent.files[i]
if (selections[i]) {
if (selection) {
file.select()
} else {
console.log('deselecting file ' + i + ' of torrent ' + torrent.name)
file.deselect()
}
}
})
}
// Gets a WebTorrent handle by torrentKey
@@ -421,7 +422,7 @@ function onError (err) {
// TODO: remove this once the following bugs are fixed:
// https://bugs.chromium.org/p/chromium/issues/detail?id=490143
// https://github.com/electron/electron/issues/7212
window.testOfflineMode = function () {
window.testOfflineMode = () => {
console.log('Test, going OFFLINE')
client = window.client = new WebTorrent({
peerId: PEER_ID,

View File

@@ -32,8 +32,8 @@
<p>
Version <script>document.write(require('../package.json').version)</script>
(<script>document.write(require('webtorrent/package.json').version)</script>)
(<script>document.write(process.arch === 'x64' ? '64-bit' : '32-bit')</script>)
(<script>document.write(process.arch)</script>)
</p>
<p><script>document.write(require('../config').APP_COPYRIGHT)</script></p>
<p><script>document.write(require('../build/config').APP_COPYRIGHT)</script></p>
</body>
</html>

Binary file not shown.

Binary file not shown.

View File

@@ -1,4 +0,0 @@
#!/bin/sh
set -e
chmod +x /opt/webtorrent-desktop/WebTorrent
ln -s -f /opt/webtorrent-desktop/WebTorrent /usr/bin/webtorrent-desktop

View File

@@ -1,3 +0,0 @@
#!/bin/sh
set -e
rm /usr/bin/webtorrent-desktop

View File

@@ -1,33 +0,0 @@
[Desktop Entry]
Name=$APP_NAME
Version=1.0
GenericName=BitTorrent Client
X-GNOME-FullName=$APP_NAME
Comment=Download and share files over BitTorrent
Encoding=UTF-8
Type=Application
Icon=webtorrent-desktop
Terminal=false
Path=$APP_PATH
Exec=$EXEC_PATH %U
TryExec=$TRY_EXEC_PATH
StartupNotify=false
Categories=Network;FileTransfer;P2P;
MimeType=application/x-bittorrent;x-scheme-handler/magnet;x-scheme-handler/stream-magnet;
Actions=CreateNewTorrent;OpenTorrentFile;OpenTorrentAddress;
[Desktop Action CreateNewTorrent]
Name=Create New Torrent...
Exec=$EXEC_PATH -n
Path=$APP_PATH
[Desktop Action OpenTorrentFile]
Name=Open Torrent File...
Exec=$EXEC_PATH -o
Path=$APP_PATH
[Desktop Action OpenTorrentAddress]
Name=Open Torrent Address...
Exec=$EXEC_PATH -u
Path=$APP_PATH

View File

@@ -0,0 +1,25 @@
[Desktop Entry]
Type=Application
Name=<%= productName %>
<% if (genericName) { %>GenericName=<%= genericName %><% } %>
<% if (description) { %>Comment=<%= description %><% } %>
Icon=<%= name %>
<% if (name) { %>Exec=<%= name %> --no-sandbox %U<% } %><%/*HACK: --no-sandbox fixes an Electron 6 bug. See: #1703*/%>
Terminal=false
Actions=CreateNewTorrent;OpenTorrentFile;OpenTorrentAddress;
<% if (mimeType && mimeType.length) { %>MimeType=<%= mimeType.join(';') %>;<% } %>
<% if (categories && categories.length) { %>Categories=<%= categories.join(';') %>;<% } %>
StartupNotify=true
StartupWMClass=<%= productName %>
[Desktop Action CreateNewTorrent]
Name=Create New Torrent...
<% if (name) { %>Exec=<%= name %> --no-sandbox -n <% } %><%/*HACK: --no-sandbox fixes an Electron 6 bug. See: #1703*/%>
[Desktop Action OpenTorrentFile]
Name=Open Torrent File...
<% if (name) { %>Exec=<%= name %> --no-sandbox -o <% } %><%/*HACK: --no-sandbox fixes an Electron 6 bug. See: #1703*/%>
[Desktop Action OpenTorrentAddress]
Name=Open Torrent Address...
<% if (name) { %>Exec=<%= name %> --no-sandbox -u <% } %><%/*HACK: --no-sandbox fixes an Electron 6 bug. See: #1703*/%>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -71,7 +71,6 @@ table {
.app {
-webkit-user-select: none;
-webkit-app-region: drag;
height: 100%;
display: flex;
flex-flow: column;
@@ -143,6 +142,7 @@ table {
*/
.header {
-webkit-app-region: drag;
background: rgb(40, 40, 40);
border-bottom: 1px solid rgb(30, 30, 30);
height: 38px; /* vertically center OS menu buttons (OS X) */
@@ -322,6 +322,10 @@ textarea,
* TORRENT LIST
*/
.torrent-list {
height: 100%;
}
.torrent {
background: linear-gradient(to bottom right, #4B79A1, #283E51);
background-repeat: no-repeat;
@@ -558,6 +562,13 @@ body.drag .app::after {
width: 100%;
}
.player .name {
font-size: 20px;
font-weight: bold;
line-height: 1.5em;
margin-bottom: 6px;
}
/*
* PLAYER CONTROLS
*/
@@ -623,6 +634,11 @@ body.drag .app::after {
margin-top: 6px;
}
.player .controls .icon.multi-audio {
font-size: 26px;
margin-top: 6px;
}
.player .controls .icon.fullscreen {
font-size: 26px;
margin-right: 15px;

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,15 +1,18 @@
const electron = require('electron')
const config = require('./config')
console.log('Mocking electron.dialog.showOpenDialog...')
electron.dialog.showOpenDialog = function (win, opts, cb) {
const ret = /select.*torrent file/i.test(opts.title)
console.log('Mocking electron.dialog.showOpenDialogSync...')
electron.dialog.showOpenDialogSync = showOpenDialogSync
function showOpenDialogSync (win, opts) {
return /select.*torrent file/i.test(opts.title)
? config.TORRENT_FILES
: config.SEED_FILES
cb(ret)
}
console.log('Mocking electron.remote.dialog.showSaveDialog...')
electron.dialog.showSaveDialog = function (win, opts, cb) {
cb(config.SAVED_TORRENT_FILE)
console.log('Mocking electron.dialog.showSaveDialogSync...')
electron.dialog.showSaveDialogSync = showSaveDialogSync
function showSaveDialogSync (win, opts) {
return config.SAVED_TORRENT_FILE
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 966 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

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