sponsor: add new button and dialog

Issue: https://github.com/pybricks/support/issues/719
This commit is contained in:
David Lechner
2022-10-28 18:01:39 -05:00
committed by David Lechner
parent ede6f80f49
commit 03f6c004db
16 changed files with 168 additions and 0 deletions
+2
View File
@@ -6,8 +6,10 @@
### Added
- Added feature create new empty file ([pybricks-code#771]).
- Added sponsor button ([support#719]).
[pybricks-code#771]: https://github.com/pybricks/pybricks-code/issues/771
[support#719]: https://github.com/pybricks/support/issues/719
## [2.0.0-beta.9] - 2022-10-27
+2
View File
@@ -12,6 +12,7 @@ import Activities from '../activities/Activities';
import { InstallPybricksDialog } from '../firmware/installPybricksDialog/InstallPybricksDialog';
import RestoreOfficialDialog from '../firmware/restoreOfficialDialog/RestoreOfficialDialog';
import { useSettingIsShowDocsEnabled } from '../settings/hooks';
import SponsorDialog from '../sponsor/SponsorDialog';
import StatusBar from '../status-bar/StatusBar';
import Toolbar from '../toolbar/Toolbar';
import Tour from '../tour/Tour';
@@ -235,6 +236,7 @@ const App: React.VFC = () => {
<Tour />
<InstallPybricksDialog />
<RestoreOfficialDialog />
<SponsorDialog />
</div>
);
};
+2
View File
@@ -22,6 +22,7 @@ import {
Edit,
Error,
Export,
Heart,
Help,
Import,
InfoSign,
@@ -65,6 +66,7 @@ export const IconSvgPaths16 = {
Edit,
Error,
Export,
Heart,
Help,
Import,
InfoSign,
+2
View File
@@ -11,6 +11,7 @@ import fileStorage from './fileStorage/reducers';
import firmware from './firmware/reducers';
import hub from './hub/reducers';
import bootloader from './lwp3-bootloader/reducers';
import sponsor from './sponsor/reducers';
import tour from './tour/reducers';
/**
@@ -26,6 +27,7 @@ export const rootReducer = combineReducers({
firmware,
hub,
tour,
sponsor,
});
/**
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

+61
View File
@@ -0,0 +1,61 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors
import { AnchorButton, Classes, Dialog, Intent } from '@blueprintjs/core';
import classNames from 'classnames';
import React from 'react';
import { useDispatch } from 'react-redux';
import { useSelector } from '../reducers';
import ExternalLinkIcon from '../utils/ExternalLinkIcon';
import patreonLogo from './Digital-Patreon-Logo_White.png';
import gitHubIcon from './GitHub-Mark-Light-32px.png';
import { sponsorHideDialog } from './actions';
import { useI18n } from './i18n';
const SponsorDialog: React.VoidFunctionComponent = () => {
const { showDialog } = useSelector((s) => s.sponsor);
const dispatch = useDispatch();
const i18n = useI18n();
return (
<Dialog
title={i18n.translate('title', { pybricks: 'Pybricks' })}
isOpen={showDialog}
onClose={() => dispatch(sponsorHideDialog())}
icon="heart"
>
<div className={classNames(Classes.DIALOG_BODY, Classes.RUNNING_TEXT)}>
<p>
<AnchorButton
large={true}
intent={Intent.PRIMARY}
icon={<img src={gitHubIcon} width={24} height={24} />}
fill={true}
href="https://github.com/sponsors/pybricks"
target="_blank"
rel="noreferrer"
>
GitHub Sponsors
<ExternalLinkIcon />
</AnchorButton>
</p>
<p>
<AnchorButton
large={true}
intent={Intent.PRIMARY}
icon={<img src={patreonLogo} width={24} height={24} />}
fill={true}
href="https://www.patreon.com/pybricks"
target="_blank"
rel="noreferrer"
>
Patreon
<ExternalLinkIcon />
</AnchorButton>
</p>
</div>
</Dialog>
);
};
export default SponsorDialog;
+12
View File
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors
import { createAction } from '../actions';
export const sponsorShowDialog = createAction(() => ({
type: 'sponsor.action.showDialog',
}));
export const sponsorHideDialog = createAction(() => ({
type: 'sponsor.action.hideDialog',
}));
+12
View File
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors
import { useI18n as useShopifyI18n } from '@shopify/react-i18n';
import type { TypedI18n } from '../i18n';
import type translations from './translations/en.json';
export function useI18n(): TypedI18n<typeof translations> {
// istanbul ignore next: babel-loader rewrites this line
const [i18n] = useShopifyI18n();
return i18n;
}
+22
View File
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors
import { Reducer, combineReducers } from '@reduxjs/toolkit';
import { sponsorHideDialog, sponsorShowDialog } from './actions';
/** A list of open files in the order they should be displayed to the user. */
const showDialog: Reducer<boolean> = (state = false, action) => {
if (sponsorShowDialog.matches(action)) {
return true;
}
if (sponsorHideDialog.matches(action)) {
return false;
}
return state;
};
export default combineReducers({
showDialog,
});
+3
View File
@@ -0,0 +1,3 @@
{
"title": "Sponsor {pybricks}"
}
+3
View File
@@ -8,6 +8,7 @@ import { Toolbar as UtilsToolbar } from '../components/toolbar/Toolbar';
import BluetoothButton from './buttons/bluetooth/BluetoothButton';
import ReplButton from './buttons/repl/ReplButton';
import RunButton from './buttons/run/RunButton';
import SponsorButton from './buttons/sponsor/SponsorButton';
import StopButton from './buttons/stop/StopButton';
import TourButton from './buttons/tour/TourButton';
@@ -16,6 +17,7 @@ import './toolbar.scss';
// matches ID in tour component
const bluetoothButtonId = 'pb-toolbar-bluetooth-button';
const runButtonId = 'pb-toolbar-run-button';
const sponsorButtonId = 'pb-toolbar-sponsor-button';
const tourButtonId = 'pb-toolbar-tour-button';
const Toolbar: React.VFC = () => {
@@ -34,6 +36,7 @@ const Toolbar: React.VFC = () => {
<ReplButton id={replButtonId} />
</ButtonGroup>
<ButtonGroup className="pb-toolbar-group pb-align-right">
<SponsorButton id={sponsorButtonId} />
<TourButton id={tourButtonId} />
</ButtonGroup>
</UtilsToolbar>
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2020-2022 The Pybricks Authors
import React from 'react';
import { useDispatch } from 'react-redux';
import { sponsorShowDialog } from '../../../sponsor/actions';
import ActionButton, { ActionButtonProps } from '../../ActionButton';
import { useI18n } from './i18n';
import icon from './icon.svg';
type SponsorButtonProps = Pick<ActionButtonProps, 'id'>;
const SponsorButton: React.VoidFunctionComponent<SponsorButtonProps> = ({ id }) => {
const i18n = useI18n();
const dispatch = useDispatch();
return (
<ActionButton
id={id}
label={i18n.translate('label')}
tooltip={i18n.translate('tooltip.action')}
icon={icon}
onAction={() => dispatch(sponsorShowDialog())}
/>
);
};
export default SponsorButton;
+12
View File
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors
import { useI18n as useShopifyI18n } from '@shopify/react-i18n';
import type { TypedI18n } from '../../../i18n';
import type translations from './translations/en.json';
export function useI18n(): TypedI18n<typeof translations> {
// istanbul ignore next: babel-loader rewrites this line
const [i18n] = useShopifyI18n();
return i18n;
}
+1
View File
@@ -0,0 +1 @@
<svg width="50" height="50" version="1.1" viewBox="0 0 26.458 26.458" xmlns="http://www.w3.org/2000/svg"><g fill="#fff"><ellipse cx="8.4895" cy="10.354" rx="5.5574" ry="5.2395"/><ellipse cx="17.969" cy="10.354" rx="5.557" ry="5.2395"/><path transform="matrix(.45296 0 0 .21945 6.7978 8.0573)" d="m32.572 28.708-18.381 31.836-18.381-31.836z"/><rect x="10.91" y="9.6552" width="3.9422" height="5.7124" rx="3.1183" ry="4.4767"/></g></svg>

After

Width:  |  Height:  |  Size: 436 B

@@ -0,0 +1,6 @@
{
"label": "Sponsor",
"tooltip": {
"action": "Learn how you can help support Pybricks development."
}
}