aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/services
diff options
context:
space:
mode:
authorLibravatar muhamedsalih-tw <104364298+muhamedsalih-tw@users.noreply.github.com>2022-11-19 15:21:09 +0530
committerLibravatar GitHub <noreply@github.com>2022-11-19 09:51:09 +0000
commita051331680b21f20201a47601d69505a4cfa9e40 (patch)
treef98dd4bc668c9814d58c0e49170aeeb19c2fe1de /src/components/services
parent6.2.1-nightly.46 [skip ci] (diff)
downloadferdium-app-a051331680b21f20201a47601d69505a4cfa9e40.tar.gz
ferdium-app-a051331680b21f20201a47601d69505a4cfa9e40.tar.zst
ferdium-app-a051331680b21f20201a47601d69505a4cfa9e40.zip
Transform service components to ts (#778)
Diffstat (limited to 'src/components/services')
-rw-r--r--src/components/services/content/ConnectionLostBanner.tsx (renamed from src/components/services/content/ConnectionLostBanner.js)37
-rw-r--r--src/components/services/content/ErrorHandlers/styles.ts25
-rw-r--r--src/components/services/content/ServiceDisabled.tsx (renamed from src/components/services/content/ServiceDisabled.js)24
-rw-r--r--src/components/services/content/ServiceView.tsx (renamed from src/components/services/content/ServiceView.js)100
-rw-r--r--src/components/services/content/Services.tsx22
-rw-r--r--src/components/services/content/WebviewCrashHandler.tsx (renamed from src/components/services/content/WebviewCrashHandler.js)44
-rw-r--r--src/components/services/content/WebviewErrorHandler.tsx (renamed from src/components/services/content/ErrorHandlers/WebviewErrorHandler.js)63
7 files changed, 156 insertions, 159 deletions
diff --git a/src/components/services/content/ConnectionLostBanner.js b/src/components/services/content/ConnectionLostBanner.tsx
index f2f70ca2e..88731f3b9 100644
--- a/src/components/services/content/ConnectionLostBanner.js
+++ b/src/components/services/content/ConnectionLostBanner.tsx
@@ -1,9 +1,7 @@
1import { Component } from 'react'; 1import { Component, ReactElement } from 'react';
2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 2import { observer } from 'mobx-react';
4import injectSheet from 'react-jss'; 3import withStyles, { WithStylesProps } from 'react-jss';
5import { defineMessages, injectIntl } from 'react-intl'; 4import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl';
6
7import { mdiAlert } from '@mdi/js'; 5import { mdiAlert } from '@mdi/js';
8import { LIVE_API_FERDIUM_WEBSITE } from '../../../config'; 6import { LIVE_API_FERDIUM_WEBSITE } from '../../../config';
9import Icon from '../../ui/icon'; 7import Icon from '../../ui/icon';
@@ -23,11 +21,10 @@ const messages = defineMessages({
23 }, 21 },
24}); 22});
25 23
26let buttonTransition = 'none'; 24const buttonTransition =
27 25 window && window.matchMedia('(prefers-reduced-motion: no-preference)')
28if (window && window.matchMedia('(prefers-reduced-motion: no-preference)')) { 26 ? 'opacity 0.25s'
29 buttonTransition = 'opacity 0.25s'; 27 : 'none';
30}
31 28
32const styles = theme => ({ 29const styles = theme => ({
33 root: { 30 root: {
@@ -68,17 +65,15 @@ const styles = theme => ({
68 }, 65 },
69}); 66});
70 67
71class ConnectionLostBanner extends Component { 68interface IProps extends WithStylesProps<typeof styles>, WrappedComponentProps {
72 static propTypes = { 69 name: string;
73 classes: PropTypes.object.isRequired, 70 reload: () => void;
74 name: PropTypes.string.isRequired, 71}
75 reload: PropTypes.func.isRequired,
76 };
77
78 render() {
79 const { classes, name, reload } = this.props;
80 72
81 const { intl } = this.props; 73@observer
74class ConnectionLostBanner extends Component<IProps> {
75 render(): ReactElement {
76 const { classes, name, reload, intl } = this.props;
82 77
83 return ( 78 return (
84 <div className={classes.root}> 79 <div className={classes.root}>
@@ -101,4 +96,4 @@ class ConnectionLostBanner extends Component {
101 } 96 }
102} 97}
103 98
104export default injectIntl(injectSheet(styles)(observer(ConnectionLostBanner))); 99export default injectIntl(withStyles(styles)(ConnectionLostBanner));
diff --git a/src/components/services/content/ErrorHandlers/styles.ts b/src/components/services/content/ErrorHandlers/styles.ts
deleted file mode 100644
index 9e2509ee5..000000000
--- a/src/components/services/content/ErrorHandlers/styles.ts
+++ /dev/null
@@ -1,25 +0,0 @@
1export default theme => ({
2 component: {
3 left: 0,
4 position: 'absolute',
5 top: 0,
6 width: '100%',
7 zIndex: 0,
8 alignItems: 'center',
9 background: theme.colorWebviewErrorHandlerBackground,
10 display: 'flex',
11 flexDirection: 'column',
12 justifyContent: 'center',
13 textAlign: 'center',
14 },
15 buttonContainer: {
16 display: 'flex',
17 flexDirection: 'row',
18 height: 'auto',
19 margin: [40, 0, 20],
20
21 '& button': {
22 margin: [0, 10, 0, 10],
23 },
24 },
25});
diff --git a/src/components/services/content/ServiceDisabled.js b/src/components/services/content/ServiceDisabled.tsx
index d874a354e..2f0d439ec 100644
--- a/src/components/services/content/ServiceDisabled.js
+++ b/src/components/services/content/ServiceDisabled.tsx
@@ -1,8 +1,6 @@
1import { Component } from 'react'; 1import { Component, ReactElement } from 'react';
2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 2import { observer } from 'mobx-react';
4import { defineMessages, injectIntl } from 'react-intl'; 3import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl';
5
6import Button from '../../ui/button'; 4import Button from '../../ui/button';
7import { H1 } from '../../ui/headline'; 5import { H1 } from '../../ui/headline';
8 6
@@ -17,15 +15,15 @@ const messages = defineMessages({
17 }, 15 },
18}); 16});
19 17
20class ServiceDisabled extends Component { 18interface IProps extends WrappedComponentProps {
21 static propTypes = { 19 name: string;
22 name: PropTypes.string.isRequired, 20 enable: () => void;
23 enable: PropTypes.func.isRequired, 21}
24 };
25 22
26 render() { 23@observer
27 const { name, enable } = this.props; 24class ServiceDisabled extends Component<IProps> {
28 const { intl } = this.props; 25 render(): ReactElement {
26 const { name, enable, intl } = this.props;
29 27
30 return ( 28 return (
31 <div className="services__info-layer"> 29 <div className="services__info-layer">
@@ -40,4 +38,4 @@ class ServiceDisabled extends Component {
40 } 38 }
41} 39}
42 40
43export default injectIntl(observer(ServiceDisabled)); 41export default injectIntl(ServiceDisabled);
diff --git a/src/components/services/content/ServiceView.js b/src/components/services/content/ServiceView.tsx
index cae16ef49..e41184431 100644
--- a/src/components/services/content/ServiceView.js
+++ b/src/components/services/content/ServiceView.tsx
@@ -1,52 +1,55 @@
1/* eslint-disable react/jsx-no-useless-fragment */
2import { Component } from 'react'; 1import { Component } from 'react';
3import PropTypes from 'prop-types'; 2import { autorun, IReactionDisposer } from 'mobx';
4import { autorun } from 'mobx';
5import { observer, inject } from 'mobx-react'; 3import { observer, inject } from 'mobx-react';
6import classnames from 'classnames'; 4import classnames from 'classnames';
7import TopBarProgress from 'react-topbar-progress-indicator'; 5import TopBarProgress from 'react-topbar-progress-indicator';
8
9import ServiceModel from '../../../models/Service'; 6import ServiceModel from '../../../models/Service';
10import StatusBarTargetUrl from '../../ui/StatusBarTargetUrl'; 7import StatusBarTargetUrl from '../../ui/StatusBarTargetUrl';
11import WebviewLoader from '../../ui/WebviewLoader'; 8import WebviewLoader from '../../ui/WebviewLoader';
12import WebviewCrashHandler from './WebviewCrashHandler'; 9import WebviewCrashHandler from './WebviewCrashHandler';
13import WebviewErrorHandler from './ErrorHandlers/WebviewErrorHandler'; 10import WebviewErrorHandler from './WebviewErrorHandler';
14import ServiceDisabled from './ServiceDisabled'; 11import ServiceDisabled from './ServiceDisabled';
15import ServiceWebview from './ServiceWebview'; 12import ServiceWebview from './ServiceWebview';
16import SettingsStore from '../../../stores/SettingsStore';
17import WebControlsScreen from '../../../features/webControls/containers/WebControlsScreen'; 13import WebControlsScreen from '../../../features/webControls/containers/WebControlsScreen';
18import { CUSTOM_WEBSITE_RECIPE_ID } from '../../../config'; 14import { CUSTOM_WEBSITE_RECIPE_ID } from '../../../config';
15import { RealStores } from '../../../stores';
16
17interface IProps {
18 service: ServiceModel;
19 setWebviewRef: () => void;
20 detachService: () => void;
21 reload: () => void;
22 edit: () => void;
23 enable: () => void;
24 // isActive?: boolean; // TODO - [TECH DEBT][PROP NOT USED IN COMPONENT] check it
25 stores?: RealStores;
26 isSpellcheckerEnabled: boolean;
27}
28
29interface IState {
30 forceRepaint: boolean;
31 targetUrl: string;
32 statusBarVisible: boolean;
33}
34
35@inject('stores', 'actions')
36@observer
37class ServiceView extends Component<IProps, IState> {
38 // hibernationTimer = null; // TODO - [TS DEBT] class property not reassigned, need to find its purpose
19 39
20class ServiceView extends Component { 40 autorunDisposer: IReactionDisposer | undefined;
21 static propTypes = { 41
22 service: PropTypes.instanceOf(ServiceModel).isRequired, 42 forceRepaintTimeout: NodeJS.Timeout | undefined;
23 setWebviewReference: PropTypes.func.isRequired, 43
24 detachService: PropTypes.func.isRequired, 44 constructor(props: IProps) {
25 reload: PropTypes.func.isRequired, 45 super(props);
26 edit: PropTypes.func.isRequired, 46
27 enable: PropTypes.func.isRequired, 47 this.state = {
28 isActive: PropTypes.bool, 48 forceRepaint: false,
29 stores: PropTypes.shape({ 49 targetUrl: '',
30 settings: PropTypes.instanceOf(SettingsStore).isRequired, 50 statusBarVisible: false,
31 }).isRequired, 51 };
32 isSpellcheckerEnabled: PropTypes.bool.isRequired, 52 }
33 };
34
35 static defaultProps = {
36 isActive: false,
37 };
38
39 state = {
40 forceRepaint: false,
41 targetUrl: '',
42 statusBarVisible: false,
43 };
44
45 hibernationTimer = null;
46
47 autorunDisposer = null;
48
49 forceRepaintTimeout = null;
50 53
51 componentDidMount() { 54 componentDidMount() {
52 this.autorunDisposer = autorun(() => { 55 this.autorunDisposer = autorun(() => {
@@ -60,16 +63,16 @@ class ServiceView extends Component {
60 } 63 }
61 64
62 componentWillUnmount() { 65 componentWillUnmount() {
63 this.autorunDisposer(); 66 this.autorunDisposer!();
64 clearTimeout(this.forceRepaintTimeout); 67 clearTimeout(this.forceRepaintTimeout!);
65 clearTimeout(this.hibernationTimer); 68 // clearTimeout(this.hibernationTimer); // TODO - [TS DEBT] class property not reassigned, need to find its purpose
66 } 69 }
67 70
68 render() { 71 render() {
69 const { 72 const {
70 detachService, 73 detachService,
71 service, 74 service,
72 setWebviewReference, 75 setWebviewRef,
73 reload, 76 reload,
74 edit, 77 edit,
75 enable, 78 enable,
@@ -78,7 +81,7 @@ class ServiceView extends Component {
78 } = this.props; 81 } = this.props;
79 82
80 const { navigationBarBehaviour, navigationBarManualActive } = 83 const { navigationBarBehaviour, navigationBarManualActive } =
81 stores.settings.app; 84 stores!.settings.app;
82 85
83 const showNavBar = 86 const showNavBar =
84 navigationBarBehaviour === 'always' || 87 navigationBarBehaviour === 'always' ||
@@ -93,10 +96,9 @@ class ServiceView extends Component {
93 'services__webview--force-repaint': this.state.forceRepaint, 96 'services__webview--force-repaint': this.state.forceRepaint,
94 }); 97 });
95 98
96 let statusBar = null; 99 const statusBar = this.state.statusBarVisible ? (
97 if (this.state.statusBarVisible) { 100 <StatusBarTargetUrl text={this.state.targetUrl} />
98 statusBar = <StatusBarTargetUrl text={this.state.targetUrl} />; 101 ) : null;
99 }
100 102
101 return ( 103 return (
102 <div 104 <div
@@ -109,7 +111,7 @@ class ServiceView extends Component {
109 {service.hasCrashed && ( 111 {service.hasCrashed && (
110 <WebviewCrashHandler 112 <WebviewCrashHandler
111 name={service.recipe.name} 113 name={service.recipe.name}
112 webview={service.webview} 114 // webview={service.webview} // TODO - [TECH DEBT][PROPS NOT EXIST IN COMPONENT] check it
113 reload={reload} 115 reload={reload}
114 /> 116 />
115 )} 117 )}
@@ -138,7 +140,7 @@ class ServiceView extends Component {
138 {service.isActive && ( 140 {service.isActive && (
139 <ServiceDisabled 141 <ServiceDisabled
140 name={service.name !== '' ? service.name : service.recipe.name} 142 name={service.name !== '' ? service.name : service.recipe.name}
141 webview={service.webview} 143 // webview={service.webview} // TODO - [TECH DEBT][PROPS NOT EXIST IN COMPONENT] check it
142 enable={enable} 144 enable={enable}
143 /> 145 />
144 )} 146 )}
@@ -150,7 +152,7 @@ class ServiceView extends Component {
150 {showNavBar && <WebControlsScreen service={service} />} 152 {showNavBar && <WebControlsScreen service={service} />}
151 <ServiceWebview 153 <ServiceWebview
152 service={service} 154 service={service}
153 setWebviewReference={setWebviewReference} 155 setWebviewReference={setWebviewRef}
154 detachService={detachService} 156 detachService={detachService}
155 isSpellcheckerEnabled={isSpellcheckerEnabled} 157 isSpellcheckerEnabled={isSpellcheckerEnabled}
156 /> 158 />
@@ -187,4 +189,4 @@ class ServiceView extends Component {
187 } 189 }
188} 190}
189 191
190export default inject('stores', 'actions')(observer(ServiceView)); 192export default ServiceView;
diff --git a/src/components/services/content/Services.tsx b/src/components/services/content/Services.tsx
index 53cddd907..fa26edaa6 100644
--- a/src/components/services/content/Services.tsx
+++ b/src/components/services/content/Services.tsx
@@ -42,8 +42,8 @@ interface IProps extends WrappedComponentProps, WithStylesProps<typeof styles> {
42 services?: Service[]; 42 services?: Service[];
43 setWebviewReference: () => void; 43 setWebviewReference: () => void;
44 detachService: () => void; 44 detachService: () => void;
45 handleIPCMessage: () => void; 45 // handleIPCMessage: () => void; // TODO - [TECH DEBT] later check it
46 openWindow: () => void; 46 // openWindow: () => void; // TODO - [TECH DEBT] later check it
47 reload: (options: { serviceId: string }) => void; 47 reload: (options: { serviceId: string }) => void;
48 openSettings: (options: { path: string }) => void; 48 openSettings: (options: { path: string }) => void;
49 update: (options: { 49 update: (options: {
@@ -61,7 +61,7 @@ interface IState {
61 61
62@observer 62@observer
63class Services extends Component<IProps, IState> { 63class Services extends Component<IProps, IState> {
64 _confettiTimeout: number | null = null; 64 confettiTimeout: number | null = null;
65 65
66 constructor(props: IProps) { 66 constructor(props: IProps) {
67 super(props); 67 super(props);
@@ -72,7 +72,7 @@ class Services extends Component<IProps, IState> {
72 } 72 }
73 73
74 componentDidMount(): void { 74 componentDidMount(): void {
75 this._confettiTimeout = window.setTimeout(() => { 75 this.confettiTimeout = window.setTimeout(() => {
76 this.setState({ 76 this.setState({
77 showConfetti: false, 77 showConfetti: false,
78 }); 78 });
@@ -80,18 +80,18 @@ class Services extends Component<IProps, IState> {
80 } 80 }
81 81
82 componentWillUnmount(): void { 82 componentWillUnmount(): void {
83 if (this._confettiTimeout) { 83 if (this.confettiTimeout) {
84 clearTimeout(this._confettiTimeout); 84 clearTimeout(this.confettiTimeout);
85 } 85 }
86 } 86 }
87 87
88 render(): ReactElement { 88 render(): ReactElement {
89 const { 89 const {
90 services = [], 90 services = [],
91 handleIPCMessage, 91 // handleIPCMessage, // TODO - [TECH DEBT] later check it
92 setWebviewReference, 92 setWebviewReference,
93 detachService, 93 detachService,
94 openWindow, 94 // openWindow, // TODO - [TECH DEBT] later check it
95 reload, 95 reload,
96 openSettings, 96 openSettings,
97 update, 97 update,
@@ -136,10 +136,10 @@ class Services extends Component<IProps, IState> {
136 <ServiceView 136 <ServiceView
137 key={service.id} 137 key={service.id}
138 service={service} 138 service={service}
139 handleIPCMessage={handleIPCMessage} 139 // handleIPCMessage={handleIPCMessage} // TODO - [TECH DEBT][PROPS NOT EXIST IN COMPONENT] later check it
140 setWebviewReference={setWebviewReference} 140 setWebviewRef={setWebviewReference}
141 detachService={detachService} 141 detachService={detachService}
142 openWindow={openWindow} 142 // openWindow={openWindow} // TODO - [TECH DEBT][PROPS NOT EXIST IN COMPONENT] later check it
143 reload={() => reload({ serviceId: service.id })} 143 reload={() => reload({ serviceId: service.id })}
144 edit={() => openSettings({ path: `services/edit/${service.id}` })} 144 edit={() => openSettings({ path: `services/edit/${service.id}` })}
145 enable={() => 145 enable={() =>
diff --git a/src/components/services/content/WebviewCrashHandler.js b/src/components/services/content/WebviewCrashHandler.tsx
index 0e6e61be8..e9b17e8aa 100644
--- a/src/components/services/content/WebviewCrashHandler.js
+++ b/src/components/services/content/WebviewCrashHandler.tsx
@@ -1,9 +1,7 @@
1import { Component } from 'react'; 1import { Component, ReactElement } from 'react';
2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 2import { observer } from 'mobx-react';
4import { defineMessages, injectIntl } from 'react-intl'; 3import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl';
5import ms from 'ms'; 4import ms from 'ms';
6
7import Button from '../../ui/button'; 5import Button from '../../ui/button';
8import { H1 } from '../../ui/headline'; 6import { H1 } from '../../ui/headline';
9 7
@@ -27,21 +25,30 @@ const messages = defineMessages({
27 }, 25 },
28}); 26});
29 27
30class WebviewCrashHandler extends Component { 28interface IProps extends WrappedComponentProps {
31 static propTypes = { 29 name: string;
32 name: PropTypes.string.isRequired, 30 reload: () => void;
33 reload: PropTypes.func.isRequired, 31}
34 };
35 32
36 state = { 33interface IState {
37 countdown: ms('10s'), 34 countdown: number;
38 }; 35}
39 36
40 countdownInterval = null; 37@observer
38class WebviewCrashHandler extends Component<IProps, IState> {
39 countdownInterval: NodeJS.Timer | undefined;
41 40
42 countdownIntervalTimeout = ms('1s'); 41 countdownIntervalTimeout = ms('1s');
43 42
44 componentDidMount() { 43 constructor(props: IProps) {
44 super(props);
45
46 this.state = {
47 countdown: ms('10s'),
48 };
49 }
50
51 componentDidMount(): void {
45 const { reload } = this.props; 52 const { reload } = this.props;
46 53
47 this.countdownInterval = setInterval(() => { 54 this.countdownInterval = setInterval(() => {
@@ -51,14 +58,13 @@ class WebviewCrashHandler extends Component {
51 58
52 if (this.state.countdown <= 0) { 59 if (this.state.countdown <= 0) {
53 reload(); 60 reload();
54 clearInterval(this.countdownInterval); 61 clearInterval(this.countdownInterval!);
55 } 62 }
56 }, this.countdownIntervalTimeout); 63 }, this.countdownIntervalTimeout);
57 } 64 }
58 65
59 render() { 66 render(): ReactElement {
60 const { name, reload } = this.props; 67 const { name, reload, intl } = this.props;
61 const { intl } = this.props;
62 68
63 return ( 69 return (
64 <div className="services__info-layer"> 70 <div className="services__info-layer">
@@ -81,4 +87,4 @@ class WebviewCrashHandler extends Component {
81 } 87 }
82} 88}
83 89
84export default injectIntl(observer(WebviewCrashHandler)); 90export default injectIntl(WebviewCrashHandler);
diff --git a/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js b/src/components/services/content/WebviewErrorHandler.tsx
index a658bec8b..b99c15006 100644
--- a/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js
+++ b/src/components/services/content/WebviewErrorHandler.tsx
@@ -1,13 +1,9 @@
1import { Component } from 'react'; 1import { Component, ReactElement } from 'react';
2import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 2import { observer } from 'mobx-react';
4import { defineMessages, injectIntl } from 'react-intl'; 3import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl';
5import injectSheet from 'react-jss'; 4import withStyles, { WithStylesProps } from 'react-jss';
6 5import Button from '../../ui/button';
7import Button from '../../../ui/button'; 6import { H1 } from '../../ui/headline';
8
9import styles from './styles';
10import { H1 } from '../../../ui/headline';
11 7
12const messages = defineMessages({ 8const messages = defineMessages({
13 headline: { 9 headline: {
@@ -32,18 +28,43 @@ const messages = defineMessages({
32 }, 28 },
33}); 29});
34 30
35class WebviewErrorHandler extends Component { 31const styles = theme => ({
36 static propTypes = { 32 component: {
37 name: PropTypes.string.isRequired, 33 left: 0,
38 reload: PropTypes.func.isRequired, 34 position: 'absolute',
39 edit: PropTypes.func.isRequired, 35 top: 0,
40 errorMessage: PropTypes.string.isRequired, 36 width: '100%',
41 classes: PropTypes.object.isRequired, 37 zIndex: 0,
42 }; 38 alignItems: 'center',
39 background: theme.colorWebviewErrorHandlerBackground,
40 display: 'flex',
41 flexDirection: 'column',
42 justifyContent: 'center',
43 textAlign: 'center',
44 },
45 buttonContainer: {
46 display: 'flex',
47 flexDirection: 'row',
48 height: 'auto',
49 margin: [40, 0, 20],
50
51 '& button': {
52 margin: [0, 10, 0, 10],
53 },
54 },
55});
56
57interface IProps extends WithStylesProps<typeof styles>, WrappedComponentProps {
58 name: string;
59 reload: () => void;
60 edit: () => void;
61 errorMessage: string;
62}
43 63
44 render() { 64@observer
45 const { name, reload, edit, errorMessage, classes } = this.props; 65class WebviewErrorHandler extends Component<IProps> {
46 const { intl } = this.props; 66 render(): ReactElement {
67 const { name, reload, edit, errorMessage, classes, intl } = this.props;
47 68
48 return ( 69 return (
49 <div className={classes.component}> 70 <div className={classes.component}>
@@ -71,5 +92,5 @@ class WebviewErrorHandler extends Component {
71} 92}
72 93
73export default injectIntl( 94export default injectIntl(
74 injectSheet(styles, { injectTheme: true })(observer(WebviewErrorHandler)), 95 withStyles(styles, { injectTheme: true })(WebviewErrorHandler),
75); 96);