From 93a94d82533863bd5f85c23e4cdc2fa6a319e6f8 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford <7019101+cwillisf@users.noreply.github.com> Date: Tue, 6 Oct 2020 14:34:01 -0700 Subject: [PATCH 01/15] move About window styling into a CSS file --- .gitattributes | 1 + src/renderer/about.css | 26 ++++++++++++++++++++++++++ src/renderer/about.jsx | 23 +++++------------------ 3 files changed, 32 insertions(+), 18 deletions(-) create mode 100644 src/renderer/about.css diff --git a/.gitattributes b/.gitattributes index c49fe81..4e6bb68 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7,6 +7,7 @@ # File types which we know are binary # Prefer LF for most file types +*.css text eol=lf *.htm text eol=lf *.html text eol=lf *.js text eol=lf diff --git a/src/renderer/about.css b/src/renderer/about.css new file mode 100644 index 0000000..b804c78 --- /dev/null +++ b/src/renderer/about.css @@ -0,0 +1,26 @@ +html, body { + color: white; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: bolder; +} + +.aboutBox { + margin: 0; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.aboutLogo { + max-width: 10rem; + max-height: 10rem; +} + +.aboutText { + margin: 1.5rem; +} + +.aboutDetails { + font-size: x-small; +} diff --git a/src/renderer/about.jsx b/src/renderer/about.jsx index 9b121bc..17ffef1 100644 --- a/src/renderer/about.jsx +++ b/src/renderer/about.jsx @@ -3,33 +3,20 @@ import ReactDOM from 'react-dom'; import {productName, version} from '../../package.json'; import logo from '../icon/ScratchDesktop.svg'; +import styles from './about.css'; // TODO: localization? const AboutElement = () => ( -
{component} | {componentVersion} |
- We understand how important privacy is to our community, especially children and their parents. We wrote - this privacy policy to explain what information we collect through the Scratch application (the - “App”), how we use it, and what we're doing to keep it safe. If you have any questions - regarding this privacy policy, you can Scratch App”), how we use, process, and share it, and what we're doing to keep it safe. It + also tells you about your rights and choices with respect to your Personal Information, and how you can contact us. + >contact us if you have any questions or concerns.
-- The Scratch Team is always looking to better understand how Scratch is used around the world. To help - support this effort, Scratch only collects anonymous usage information from the Scratch App. This - information does not include any Personal Information. For purposes of this Privacy Policy, “Personal - Information” means any information relating to an identified or identifiable individual. + For the purpose of this Privacy Policy, “Information” means any information relating to an + identified or identifiable individual. The Scratch App automatically collects and stores locally the + following Information through its telemetry system: the title of your project in text form, language + setting, time zone and events related to your use of the Scratch App (namely when the Scratch App was + opened and closed, if a project file has been loaded or saved, or if a new project is created). If you + choose to turn on the telemetry sharing feature, the Scratch App will transmit this information to Scratch. + Projects created in the Scratch App are not transmitted to or accessible by Scratch.
-- The anonymous usage information we collect includes data about what parts of the app you use and basic - information about your network that allows us to roughly estimate what part of the world you are located - in. We also may collect general information about the device that you are using, such as make, model, - operating system and screen resolution. We do not collect device identifiers, such as advertising IDs, MAC - addresses, or IP addresses. We do not associate any of this information with an identified or identifiable - individual. -
-We use this Information for the following purposes:
+ If you are located in the European Economic Area, the United Kingdom or Switzerland, we only process your + Information based on a valid legal ground. A “legal ground” is a reason that justifies our use + of your Information. In this case, we or a third party have a legitimate interest in using your Information + (if you choose to allow the Scratch App to send the Scratch team your Information) to create, analyze and + share your aggregated or de-identified Information for research purposes, to analyze and enhance your + learning experience on the Scratch App and otherwise ensure and improve the safety, security, and + performance of the Scratch App. We only rely on our or a third party’s legitimate interests to process your + Information when these interests are not overridden by your rights and interests. +
++ We disclose information that we collect through the Scratch App to third parties in the following + circumstances: +
++ The Scratch Foundation is a 501(c)(3) nonprofit organization. As such, the Children's Online Privacy + Protection Act (COPPA) does not apply to Scratch. Nevertheless, Scratch takes children's privacy + seriously. Scratch collects only minimal information from its users, and only uses and discloses + information to provide the services and for limited other purposes, such as research, as described in this + Privacy Policy. +
++ Scratch does not collect information from a student's education record, as defined by the Family + Educational Rights and Privacy Act (FERPA). Scratch does not disclose information of students to any third + parties except as described in this Privacy Policy. +
++ If you are located in the European Economic Area, the United Kingdom or Switzerland, you have certain + rights in relation to your Information: +
++ In addition to the above-mentioned rights, you also have the right to lodge a complaint with a competent + supervisory authority subject to applicable law. However, there are exceptions and limitations to each of + these rights. We may, for example, refuse to act on a request if the request is manifestly unfounded or + excessive, or if the request is likely to adversely affect the rights and freedoms of others, prejudice the + execution or enforcement of the law, interfere with pending or future litigation, or infringe applicable + law. To submit a request to exercise your rights, please contact help@scratch.mit.edu for assistance. +
++ We take measures to delete your Information or keep it in a form that does not allow you to be identified + when this Information is no longer necessary for the purposes for which we process it, unless we are + required by law to keep this Information for a longer period. When determining the retention period, we + take into account various criteria, such as the type of services requested by or provided to you, the + nature and length of our relationship with you, possible re-enrollment with our services, the impact on the + services we provide to you if we delete some Information from or about you, mandatory retention periods + provided by law and the statute of limitations. +
++ Scratch has in place administrative, physical, and technical procedures that are intended to protect the + Information we collect on the Scratch App against accidental or unlawful destruction, accidental loss, + unauthorized alteration, unauthorized disclosure or access, misuse, and any other unlawful form of + processing of the Information. However, as effective as these measures are, no security system is + impenetrable. We cannot completely guarantee the security of our databases, nor can we guarantee that the + Information you supply will not be intercepted while being transmitted to us over the Internet. +
++ We may transfer your Information to countries other than the country where you are located, including to + the U.S. (where our Scratch servers are located) or any other country in which we or our service providers + maintain facilities. If you are located in the European Economic Area, the United Kingdom or Switzerland, + or other regions with laws governing data collection and use that may differ from U.S. law, please note + that we may transfer your Information to a country and jurisdiction that does not have the same data + protection laws as your jurisdiction. We apply appropriate safeguards to the Information processed and + transferred on our behalf. Please contact us for more information on the safeguards used. +
++ We review our Privacy Policy on a periodic basis, and we may modify our policies as appropriate. We will + notify you of any material changes. We encourage you to review our Privacy Policy on a regular basis. The + “Last Updated” date at the top of this page indicates when this Privacy Policy was last + revised. Your continued use of the Scratch App following these changes means that you accept the revised + Privacy Policy. +
++ The Scratch Foundation is the entity responsible for the processing of your Information. If you have any + questions about this Privacy Policy, or if you would like to exercise your rights to your Information, you + may contact us at help@scratch.mit.edu or via mail at: +
+View the Privacy Policy... From 25072c00463cfaf151334506c81e3548b935abf6 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford <7019101+cwillisf@users.noreply.github.com> Date: Tue, 17 Nov 2020 15:02:47 -0800 Subject: [PATCH 10/15] pass about menu items to GUI --- src/main/ScratchDesktopTelemetry.js | 8 ++++++++ src/main/telemetry/TelemetryClient.js | 3 +++ src/renderer/app.jsx | 18 +++++++++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/main/ScratchDesktopTelemetry.js b/src/main/ScratchDesktopTelemetry.js index ec27205..1dbecf0 100644 --- a/src/main/ScratchDesktopTelemetry.js +++ b/src/main/ScratchDesktopTelemetry.js @@ -36,6 +36,9 @@ class ScratchDesktopTelemetry { set didOptIn (value) { this._telemetryClient.didOptIn = value; } + clearDidOptIn () { + this._telemetryClient.clearDidOptIn(); + } appWasOpened () { this._telemetryClient.addEvent('app::open', {...EVENT_TEMPLATE, ...APP_INFO}); @@ -95,6 +98,11 @@ ipcMain.on('getTelemetryDidOptIn', event => { }); ipcMain.on('setTelemetryDidOptIn', (event, arg) => { scratchDesktopTelemetrySingleton.didOptIn = arg; + event.returnValue = null; +}); +ipcMain.on('clearTelemetryDidOptIn', event => { + scratchDesktopTelemetrySingleton.clearDidOptIn(); + event.returnValue = null; }); ipcMain.on('projectDidLoad', (event, arg) => { scratchDesktopTelemetrySingleton.projectDidLoad(arg); diff --git a/src/main/telemetry/TelemetryClient.js b/src/main/telemetry/TelemetryClient.js index c38cb5b..fafda8b 100644 --- a/src/main/telemetry/TelemetryClient.js +++ b/src/main/telemetry/TelemetryClient.js @@ -185,6 +185,9 @@ class TelemetryClient { set didOptIn (value) { this._store.set('optIn', !!value); } + clearDidOptIn () { + this._store.delete('optIn'); + } /** * Semi-persistent unique ID for this client diff --git a/src/renderer/app.jsx b/src/renderer/app.jsx index 8fff8cf..9fa906e 100644 --- a/src/renderer/app.jsx +++ b/src/renderer/app.jsx @@ -116,7 +116,23 @@ const ScratchDesktopHOC = function (WrappedComponent) { canSave={false} isScratchDesktop showTelemetryModal={shouldShowTelemetryModal} - onClickAbout={this.handleClickAbout} + onClickAbout={[ + { + title: 'About', + onClick: () => this.handleClickAbout() + }, + { + title: 'Privacy Policy', + onClick: () => showPrivacyPolicy() + }, + { + title: 'Telemetry Settings', + onClick: () => { + // set to null (non-Boolean) to cause app to ask again + ipcRenderer.sendSync('clearTelemetryDidOptIn'); + } + } + ]} onProjectTelemetryEvent={this.handleProjectTelemetryEvent} onShowPrivacyPolicy={showPrivacyPolicy} onStorageInit={this.handleStorageInit} From afb29bfdefa4c811a50112f5a3758e663b5122b4 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford <7019101+cwillisf@users.noreply.github.com> Date: Wed, 18 Nov 2020 15:34:01 -0800 Subject: [PATCH 11/15] use openTelemetryModal instead of showTelemetryModal --- src/renderer/app.jsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/renderer/app.jsx b/src/renderer/app.jsx index 9fa906e..aaff2ae 100644 --- a/src/renderer/app.jsx +++ b/src/renderer/app.jsx @@ -20,7 +20,8 @@ import { } from 'scratch-gui/src/reducers/project-state'; import { openLoadingProject, - closeLoadingProject + closeLoadingProject, + openTelemetryModal } from 'scratch-gui/src/reducers/modals'; import ElectronStorageHelper from '../common/ElectronStorageHelper'; @@ -127,10 +128,7 @@ const ScratchDesktopHOC = function (WrappedComponent) { }, { title: 'Telemetry Settings', - onClick: () => { - // set to null (non-Boolean) to cause app to ask again - ipcRenderer.sendSync('clearTelemetryDidOptIn'); - } + onClick: () => this.props.onTelemetrySettingsClicked() } ]} onProjectTelemetryEvent={this.handleProjectTelemetryEvent} @@ -154,6 +152,7 @@ const ScratchDesktopHOC = function (WrappedComponent) { onLoadingCompleted: PropTypes.func, onLoadingStarted: PropTypes.func, onRequestNewProject: PropTypes.func, + onTelemetrySettingsClicked: PropTypes.func, vm: PropTypes.instanceOf(VM).isRequired }; const mapStateToProps = state => { @@ -182,7 +181,8 @@ const ScratchDesktopHOC = function (WrappedComponent) { const canSaveToServer = false; return dispatch(onLoadedProject(loadingState, canSaveToServer, loadSuccess)); }, - onRequestNewProject: () => dispatch(requestNewProject(false)) + onRequestNewProject: () => dispatch(requestNewProject(false)), + onTelemetrySettingsClicked: () => dispatch(openTelemetryModal()) }); return connect(mapStateToProps, mapDispatchToProps)(ScratchDesktopComponent); From d56a3c58101a92625bd21ab155aae855fdeda823 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford <7019101+cwillisf@users.noreply.github.com> Date: Wed, 2 Dec 2020 14:03:57 -0800 Subject: [PATCH 12/15] keep telemetry modal state in sync with main process --- src/renderer/app.jsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/renderer/app.jsx b/src/renderer/app.jsx index aaff2ae..5d728a5 100644 --- a/src/renderer/app.jsx +++ b/src/renderer/app.jsx @@ -99,15 +99,18 @@ const ScratchDesktopHOC = function (WrappedComponent) { } handleTelemetryModalOptIn () { ipcRenderer.send('setTelemetryDidOptIn', true); + this.forceUpdate(); } handleTelemetryModalOptOut () { ipcRenderer.send('setTelemetryDidOptIn', false); + this.forceUpdate(); } handleUpdateProjectTitle (newTitle) { this.setState({projectTitle: newTitle}); } render () { - const shouldShowTelemetryModal = (typeof ipcRenderer.sendSync('getTelemetryDidOptIn') !== 'boolean'); + const currentTelemetryState = ipcRenderer.sendSync('getTelemetryDidOptIn'); + const shouldShowTelemetryModal = (typeof currentTelemetryState !== 'boolean'); const childProps = omit(this.props, Object.keys(ScratchDesktopComponent.propTypes)); @@ -116,6 +119,7 @@ const ScratchDesktopHOC = function (WrappedComponent) { canModifyCloudData={false} canSave={false} isScratchDesktop + isTelemetryEnabled={currentTelemetryState} showTelemetryModal={shouldShowTelemetryModal} onClickAbout={[ { From 6e840825ccddf1f0d29ef441ff3306fee9643d5f Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford <7019101+cwillisf@users.noreply.github.com> Date: Wed, 2 Dec 2020 14:24:58 -0800 Subject: [PATCH 13/15] apply feedback from design team --- src/renderer/about.jsx | 10 ---------- src/renderer/app.jsx | 2 +- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/renderer/about.jsx b/src/renderer/about.jsx index af57688..204b829 100644 --- a/src/renderer/about.jsx +++ b/src/renderer/about.jsx @@ -3,7 +3,6 @@ import {productName, version} from '../../package.json'; import logo from '../icon/ScratchDesktop.svg'; import styles from './about.css'; -import showPrivacyPolicy from './showPrivacyPolicy'; const AboutElement = () => (