aboutsummaryrefslogtreecommitdiffstats
path: root/src/features
diff options
context:
space:
mode:
authorLibravatar Bennett <hello@vantezzen.io>2020-04-17 14:32:53 +0200
committerLibravatar GitHub <noreply@github.com>2020-04-17 13:32:53 +0100
commit3239172af9fb68226e1e11392b16f833b726ad72 (patch)
treefdafdea17c8873cffdec64351e532ffdb2c7d233 /src/features
parentNew Crowdin translations (#570) (diff)
downloadferdium-app-3239172af9fb68226e1e11392b16f833b726ad72.tar.gz
ferdium-app-3239172af9fb68226e1e11392b16f833b726ad72.tar.zst
ferdium-app-3239172af9fb68226e1e11392b16f833b726ad72.zip
Merge Franz 5.5.0 beta.1 and 2 (#549)
* Automatic i18n update (i18n.meetfranz.com) * Fix zoom not working * Automatic i18n update (i18n.meetfranz.com) * Automatic i18n update (i18n.meetfranz.com) * Add environment variable FRANZ_APPDATA_DIR * Add environment variable for config FRANZ_APPDATA_DIR * fix stuff that shouldn't need fixing in the first place * notarize app * bump version to 5.4.1 * Automatic i18n update (i18n.meetfranz.com) * Automatic i18n update (i18n.meetfranz.com) * Automatic i18n update (i18n.meetfranz.com) * Automatic i18n update (i18n.meetfranz.com) * Automatic i18n update (i18n.meetfranz.com) * Automatic i18n update (i18n.meetfranz.com) * Automatic i18n update (i18n.meetfranz.com) * Automatic i18n update (i18n.meetfranz.com) * Automatic i18n update (i18n.meetfranz.com) * Automatic i18n update (i18n.meetfranz.com) * Automatic i18n update (i18n.meetfranz.com) * Automatic i18n update (i18n.meetfranz.com) * Automatic i18n update (i18n.meetfranz.com) * Automatic i18n update (i18n.meetfranz.com) * update to electron 7.1.7 * bump version to 5.5.0 * Automatic i18n update (i18n.meetfranz.com) * Bump electron to 7.1.10 * plan changes * filter plan variants * add missing string * Automatic i18n update (i18n.meetfranz.com) * Automatic i18n update (i18n.meetfranz.com) * Automatic i18n update (i18n.meetfranz.com) * Replace/remove deprecated electron function calls Electron replaced several function calls with object properties. Franz still uses some of these deprecated functions, so this commit will replace these with their new property counterpart. This commit is only transferring the changes made in getferdi/ferdi#371 and getferdi/ferdi#384 into the upstream repository. * Automatic i18n update (i18n.meetfranz.com) * Automatic i18n update (i18n.meetfranz.com) * Update to electron 8.0.1 * feat(Service): Add service hibernation to save system resources * Fix linting issues * Automatic i18n update (i18n.meetfranz.com) * Automatic i18n update (i18n.meetfranz.com) * Bump version to electron 8.1.1 * update strings * update electron-notarize * Automatic i18n update (i18n.meetfranz.com) * Automatic i18n update (i18n.meetfranz.com) * Automatic i18n update (i18n.meetfranz.com) * Add audio & video permission request for cataline * Automatic i18n update (i18n.meetfranz.com) * bump version to beta 1 * Automatic i18n update (i18n.meetfranz.com) * enable external links * Fix main content href * Automatic i18n update (i18n.meetfranz.com) * fix(Service): Fix issue with user agent override in service workers * Automatic i18n update (i18n.meetfranz.com) * fix macOS string replacement * Automatic i18n update (i18n.meetfranz.com) * fix(Experimental): Fix Google signin * fix(Service): Add integrity checks to prevent services recipes getting lost * Remove service reload on app-resume * update strings * bump version to beta 2 * Automatic i18n update (i18n.meetfranz.com) * bump electron-builder and electron-updater deps * test video permissions * fix `extendInfo` keys * fix typo * fix permission request * update camera/microphone entitlements * Automatic i18n update (i18n.meetfranz.com) * Test screen capture permissions * unpack `mac-screen-capture-permissions` * don't require localstorage temp key for permissions request * move macOS permission request to main process * Fix checking for permissions * fix(macOS): Ask the user to move Franz to the `/Applications` Folder * only try to recover recipe when user is online * update service request link * Update changelog * Reset `service.lostRecipeReloadAttempt` once service is alive again * Update translations * Fix crash on macOS * Fix merge errors * Fix lint * Disable ConnectionLostBanner * #551 Add information about Ferdi to the user agent * Fix requested changes * Remove tsbuildinfo files * Add .tsbuildinfo files to gitignore * Fix "Cannot destructure property 'app' of '_electron.remote' as it is undefined" Co-authored-by: FranzBot <i18n@meetfranz.com> Co-authored-by: Makazzz <makazzzpro@live.ca> Co-authored-by: Stefan Malzner <stefan@adlk.io>
Diffstat (limited to 'src/features')
-rw-r--r--src/features/announcements/components/AnnouncementScreen.js41
-rw-r--r--src/features/planSelection/components/PlanItem.js19
-rw-r--r--src/features/planSelection/components/PlanSelection.js76
-rw-r--r--src/features/planSelection/containers/PlanSelectionScreen.js4
4 files changed, 81 insertions, 59 deletions
diff --git a/src/features/announcements/components/AnnouncementScreen.js b/src/features/announcements/components/AnnouncementScreen.js
index 38de2dbc8..2f25e7139 100644
--- a/src/features/announcements/components/AnnouncementScreen.js
+++ b/src/features/announcements/components/AnnouncementScreen.js
@@ -192,6 +192,11 @@ class AnnouncementScreen extends Component {
192 stores: PropTypes.shape({ 192 stores: PropTypes.shape({
193 ui: PropTypes.instanceOf(UIStore).isRequired, 193 ui: PropTypes.instanceOf(UIStore).isRequired,
194 }).isRequired, 194 }).isRequired,
195 actions: PropTypes.shape({
196 app: PropTypes.shape({
197 openExternalUrl: PropTypes.func.isRequired,
198 }).isRequired,
199 }).isRequired,
195 }; 200 };
196 201
197 static contextTypes = { 202 static contextTypes = {
@@ -199,7 +204,7 @@ class AnnouncementScreen extends Component {
199 }; 204 };
200 205
201 render() { 206 render() {
202 const { classes, stores } = this.props; 207 const { classes, stores, actions } = this.props;
203 const { intl } = this.context; 208 const { intl } = this.context;
204 const { changelog, announcement } = announcementsStore; 209 const { changelog, announcement } = announcementsStore;
205 const themeImage = stores.ui.isDarkThemeActive ? 'dark' : 'light'; 210 const themeImage = stores.ui.isDarkThemeActive ? 'dark' : 'light';
@@ -223,14 +228,23 @@ class AnnouncementScreen extends Component {
223 __html: marked(announcement.main.text, markedOptions), 228 __html: marked(announcement.main.text, markedOptions),
224 }} 229 }}
225 /> 230 />
226 <div className={classes.mainCtaButton}> 231 {(announcement.main.cta.label || announcement.main.cta.href) && (
227 <Button 232 <div className={classes.mainCtaButton}>
228 label={announcement.main.cta.label} 233 <Button
229 onClick={() => { 234 label={announcement.main.cta.label}
230 window.location.href = `#${announcement.main.cta.href}`; 235 onClick={() => {
231 }} 236 const {
232 /> 237 href,
233 </div> 238 } = announcement.main.cta;
239 if (announcement.main.cta.href.startsWith('http')) {
240 actions.app.openExternalUrl({ url: href });
241 } else {
242 window.location.href = `#${href}`;
243 }
244 }}
245 />
246 </div>
247 )}
234 </div> 248 </div>
235 </div> 249 </div>
236 </div> 250 </div>
@@ -250,7 +264,14 @@ class AnnouncementScreen extends Component {
250 <Button 264 <Button
251 label={announcement.spotlight.cta.label} 265 label={announcement.spotlight.cta.label}
252 onClick={() => { 266 onClick={() => {
253 window.location.href = `#${announcement.spotlight.cta.href}`; 267 const {
268 href,
269 } = announcement.spotlight.cta;
270 if (announcement.spotlight.cta.href.startsWith('http')) {
271 actions.app.openExternalUrl({ url: href });
272 } else {
273 window.location.href = `#${href}`;
274 }
254 }} 275 }}
255 /> 276 />
256 </div> 277 </div>
diff --git a/src/features/planSelection/components/PlanItem.js b/src/features/planSelection/components/PlanItem.js
index ec061377b..3855fedf1 100644
--- a/src/features/planSelection/components/PlanItem.js
+++ b/src/features/planSelection/components/PlanItem.js
@@ -49,6 +49,7 @@ const styles = theme => ({
49 priceWrapper: { 49 priceWrapper: {
50 height: 50, 50 height: 50,
51 marginBottom: 0, 51 marginBottom: 0,
52 marginTop: ({ text }) => (!text ? 15 : 0),
52 }, 53 },
53 price: { 54 price: {
54 fontSize: 50, 55 fontSize: 50,
@@ -64,7 +65,7 @@ const styles = theme => ({
64 cta: { 65 cta: {
65 background: theme.styleTypes.primary.accent, 66 background: theme.styleTypes.primary.accent,
66 color: theme.styleTypes.primary.contrast, 67 color: theme.styleTypes.primary.contrast,
67 margin: [40, 'auto', 0, 'auto'], 68 margin: [30, 'auto', 0, 'auto'],
68 }, 69 },
69 divider: { 70 divider: {
70 width: 40, 71 width: 40,
@@ -77,10 +78,14 @@ const styles = theme => ({
77 background: color(theme.styleTypes.primary.accent).darken(0.25).hex(), 78 background: color(theme.styleTypes.primary.accent).darken(0.25).hex(),
78 color: theme.styleTypes.primary.contrast, 79 color: theme.styleTypes.primary.contrast,
79 position: 'relative', 80 position: 'relative',
81 height: 'auto',
80 }, 82 },
81 content: { 83 content: {
82 padding: [10, 20, 20], 84 padding: [10, 20, 20],
83 background: '#EFEFEF', 85 background: '#EFEFEF',
86 display: 'flex',
87 flexDirection: 'column',
88 justifyContent: 'space-between',
84 }, 89 },
85 simpleCTA: { 90 simpleCTA: {
86 background: 'none', 91 background: 'none',
@@ -167,10 +172,14 @@ export default @observer @injectSheet(styles) class PlanItem extends Component {
167 </div> 172 </div>
168 )} 173 )}
169 <H2 className={classes.planName}>{name}</H2> 174 <H2 className={classes.planName}>{name}</H2>
170 <p className={classes.text}> 175 {text && (
171 {text} 176 <>
172 </p> 177 <p className={classes.text}>
173 <hr className={classes.divider} /> 178 {text}
179 </p>
180 <hr className={classes.divider} />
181 </>
182 )}
174 <p className={classes.priceWrapper}> 183 <p className={classes.priceWrapper}>
175 <span className={classes.currency}>{currency}</span> 184 <span className={classes.currency}>{currency}</span>
176 <span className={classes.price}> 185 <span className={classes.price}>
diff --git a/src/features/planSelection/components/PlanSelection.js b/src/features/planSelection/components/PlanSelection.js
index 4bf5238dd..6f0dd30ad 100644
--- a/src/features/planSelection/components/PlanSelection.js
+++ b/src/features/planSelection/components/PlanSelection.js
@@ -6,7 +6,7 @@ import { defineMessages, intlShape } from 'react-intl';
6import { H1, H2, Icon } from '@meetfranz/ui'; 6import { H1, H2, Icon } from '@meetfranz/ui';
7import color from 'color'; 7import color from 'color';
8 8
9import { mdiRocket, mdiArrowRight } from '@mdi/js'; 9import { mdiArrowRight } from '@mdi/js';
10import PlanItem from './PlanItem'; 10import PlanItem from './PlanItem';
11import { i18nPlanName } from '../../../helpers/plan-helpers'; 11import { i18nPlanName } from '../../../helpers/plan-helpers';
12import { PLANS } from '../../../config'; 12import { PLANS } from '../../../config';
@@ -79,10 +79,10 @@ const styles = theme => ({
79 overflowY: 'scroll', 79 overflowY: 'scroll',
80 }, 80 },
81 container: { 81 container: {
82 width: '80%', 82 // width: '80%',
83 height: 'auto', 83 height: 'auto',
84 background: theme.styleTypes.primary.accent, 84 // background: theme.styleTypes.primary.accent,
85 padding: 40, 85 // padding: 40,
86 borderRadius: theme.borderRadius, 86 borderRadius: theme.borderRadius,
87 maxWidth: 1000, 87 maxWidth: 1000,
88 88
@@ -104,23 +104,6 @@ const styles = theme => ({
104 boxShadow: [0, 2, 30, color('#000').alpha(0.1).rgb().string()], 104 boxShadow: [0, 2, 30, color('#000').alpha(0.1).rgb().string()],
105 }, 105 },
106 }, 106 },
107 bigIcon: {
108 background: theme.styleTypes.danger.accent,
109 width: 120,
110 height: 120,
111 display: 'flex',
112 alignItems: 'center',
113 borderRadius: '100%',
114 justifyContent: 'center',
115 margin: [-100, 'auto', 20],
116
117 '& svg': {
118 width: '80px !important',
119 height: '80px !important',
120 filter: 'drop-shadow( 0px 2px 3px rgba(0, 0, 0, 0.3))',
121 fill: theme.styleTypes.danger.contrast,
122 },
123 },
124 headline: { 107 headline: {
125 fontSize: 40, 108 fontSize: 40,
126 }, 109 },
@@ -158,7 +141,7 @@ const styles = theme => ({
158 overflow: 'scroll-x', 141 overflow: 'scroll-x',
159 }, 142 },
160 featuredPlan: { 143 featuredPlan: {
161 transform: 'scale(1.05)', 144 transform: ({ isPersonalPlanAvailable }) => (isPersonalPlanAvailable ? 'scale(1.05)' : null),
162 }, 145 },
163 disclaimer: { 146 disclaimer: {
164 textAlign: 'right', 147 textAlign: 'right',
@@ -177,8 +160,13 @@ class PlanSelection extends Component {
177 upgradeAccount: PropTypes.func.isRequired, 160 upgradeAccount: PropTypes.func.isRequired,
178 stayOnFree: PropTypes.func.isRequired, 161 stayOnFree: PropTypes.func.isRequired,
179 hadSubscription: PropTypes.bool.isRequired, 162 hadSubscription: PropTypes.bool.isRequired,
163 isPersonalPlanAvailable: PropTypes.bool,
180 }; 164 };
181 165
166 static defaultProps = {
167 isPersonalPlanAvailable: true,
168 }
169
182 static contextTypes = { 170 static contextTypes = {
183 intl: intlShape, 171 intl: intlShape,
184 }; 172 };
@@ -196,6 +184,7 @@ class PlanSelection extends Component {
196 upgradeAccount, 184 upgradeAccount,
197 stayOnFree, 185 stayOnFree,
198 hadSubscription, 186 hadSubscription,
187 isPersonalPlanAvailable,
199 } = this.props; 188 } = this.props;
200 189
201 const { intl } = this.context; 190 const { intl } = this.context;
@@ -206,15 +195,14 @@ class PlanSelection extends Component {
206 className={classes.root} 195 className={classes.root}
207 > 196 >
208 <div className={classes.container}> 197 <div className={classes.container}>
209 <div className={classes.bigIcon}>
210 <Icon icon={mdiRocket} />
211 </div>
212 <H1 className={classes.headline}>{intl.formatMessage(messages.welcome, { name: firstname })}</H1> 198 <H1 className={classes.headline}>{intl.formatMessage(messages.welcome, { name: firstname })}</H1>
213 <H2 className={classes.subheadline}>{intl.formatMessage(messages.subheadline)}</H2> 199 {isPersonalPlanAvailable && (
200 <H2 className={classes.subheadline}>{intl.formatMessage(messages.subheadline)}</H2>
201 )}
214 <div className={classes.plans}> 202 <div className={classes.plans}>
215 <PlanItem 203 <PlanItem
216 name={i18nPlanName(PLANS.FREE, intl)} 204 name={i18nPlanName(PLANS.FREE, intl)}
217 text={intl.formatMessage(messages.textFree)} 205 text={isPersonalPlanAvailable ? intl.formatMessage(messages.textFree) : null}
218 price={0} 206 price={0}
219 currency={currency} 207 currency={currency}
220 ctaLabel={intl.formatMessage(subscriptionExpired ? messages.ctaDowngradeFree : messages.ctaStayOnFree)} 208 ctaLabel={intl.formatMessage(subscriptionExpired ? messages.ctaDowngradeFree : messages.ctaStayOnFree)}
@@ -228,33 +216,35 @@ class PlanSelection extends Component {
228 </PlanItem> 216 </PlanItem>
229 <PlanItem 217 <PlanItem
230 name={i18nPlanName(plans.pro.yearly.id, intl)} 218 name={i18nPlanName(plans.pro.yearly.id, intl)}
231 text={intl.formatMessage(messages.textProfessional)} 219 text={isPersonalPlanAvailable ? intl.formatMessage(messages.textProfessional) : null}
232 price={plans.pro.yearly.price} 220 price={plans.pro.yearly.price}
233 currency={currency} 221 currency={currency}
234 ctaLabel={intl.formatMessage(hadSubscription ? messages.shortActionPro : messages.actionTrial)} 222 ctaLabel={intl.formatMessage(hadSubscription ? messages.shortActionPro : messages.actionTrial)}
235 upgrade={() => upgradeAccount(plans.pro.yearly.id)} 223 upgrade={() => upgradeAccount(plans.pro.yearly.id)}
236 className={classes.featuredPlan} 224 className={classes.featuredPlan}
237 perUser 225 perUser
238 bestValue 226 bestValue={isPersonalPlanAvailable}
239 >
240 <FeatureList
241 plan={PLANS.PRO}
242 className={classes.featureList}
243 />
244 </PlanItem>
245 <PlanItem
246 name={i18nPlanName(plans.personal.yearly.id, intl)}
247 text={intl.formatMessage(messages.textPersonal)}
248 price={plans.personal.yearly.price}
249 currency={currency}
250 ctaLabel={intl.formatMessage(hadSubscription ? messages.shortActionPersonal : messages.actionTrial)}
251 upgrade={() => upgradeAccount(plans.personal.yearly.id)}
252 > 227 >
253 <FeatureList 228 <FeatureList
254 plan={PLANS.PERSONAL} 229 plan={isPersonalPlanAvailable ? PLANS.PRO : null}
255 className={classes.featureList} 230 className={classes.featureList}
256 /> 231 />
257 </PlanItem> 232 </PlanItem>
233 {isPersonalPlanAvailable && (
234 <PlanItem
235 name={i18nPlanName(plans.personal.yearly.id, intl)}
236 text={intl.formatMessage(messages.textPersonal)}
237 price={plans.personal.yearly.price}
238 currency={currency}
239 ctaLabel={intl.formatMessage(hadSubscription ? messages.shortActionPersonal : messages.actionTrial)}
240 upgrade={() => upgradeAccount(plans.personal.yearly.id)}
241 >
242 <FeatureList
243 plan={PLANS.PERSONAL}
244 className={classes.featureList}
245 />
246 </PlanItem>
247 )}
258 </div> 248 </div>
259 <div className={classes.footer}> 249 <div className={classes.footer}>
260 <a 250 <a
diff --git a/src/features/planSelection/containers/PlanSelectionScreen.js b/src/features/planSelection/containers/PlanSelectionScreen.js
index d202c924e..e4d85cda5 100644
--- a/src/features/planSelection/containers/PlanSelectionScreen.js
+++ b/src/features/planSelection/containers/PlanSelectionScreen.js
@@ -53,7 +53,8 @@ class PlanSelectionScreen extends Component {
53 const { intl } = this.context; 53 const { intl } = this.context;
54 54
55 const { user, features } = this.props.stores; 55 const { user, features } = this.props.stores;
56 const { plans, currency } = features.features.pricingConfig; 56 const { isPersonalPlanAvailable, pricingConfig } = features.features;
57 const { plans, currency } = pricingConfig;
57 const { activateTrial } = this.props.actions.user; 58 const { activateTrial } = this.props.actions.user;
58 const { downgradeAccount, hideOverlay } = this.props.actions.planSelection; 59 const { downgradeAccount, hideOverlay } = this.props.actions.planSelection;
59 60
@@ -95,6 +96,7 @@ class PlanSelectionScreen extends Component {
95 }} 96 }}
96 subscriptionExpired={user.team && user.team.state === 'expired' && !user.team.userHasDowngraded} 97 subscriptionExpired={user.team && user.team.state === 'expired' && !user.team.userHasDowngraded}
97 hadSubscription={user.data.hadSubscription} 98 hadSubscription={user.data.hadSubscription}
99 isPersonalPlanAvailable={isPersonalPlanAvailable}
98 /> 100 />
99 </ErrorBoundary> 101 </ErrorBoundary>
100 ); 102 );