Merge branch 'development' into fix/discover-page-remove-duplicated-filters

This commit is contained in:
Botzy 2025-02-18 11:54:50 +02:00
commit 2816f7bcea
12 changed files with 203 additions and 118 deletions

View file

@ -8,6 +8,7 @@ import styles from './Button.less';
type Props = {
className?: string,
href?: string,
target?: string
title?: string,
disabled?: boolean,
tabIndex?: number,

View file

@ -0,0 +1,83 @@
// Copyright (C) 2017-2025 Smart code 203358507
@import (reference) '~@stremio/stremio-colors/less/stremio-colors.less';
.checkbox {
display: flex;
align-items: center;
overflow: visible;
.label {
display: flex;
flex-direction: row;
align-items: center;
padding: 0.5rem 0;
cursor: pointer;
span {
font-size: 0.9rem;
color: var(--primary-foreground-color);
opacity: 0.6;
}
.link {
font-size: 0.9rem;
color: var(--primary-accent-color);
&:hover {
text-decoration: underline;
}
}
}
.checkbox-container {
position: relative;
width: 1.5rem;
height: 1.5rem;
border-radius: 0.3rem;
background-color: var(--overlay-color);
padding: 0.1rem;
display: flex;
flex: none;
margin: 0 1rem 0 0.3rem;
align-items: center;
justify-content: center;
transition: all 0.2s ease-in-out;
cursor: pointer;
outline: none;
user-select: none;
outline-width: var(--focus-outline-size);
outline-color: @color-surface-light5;
outline-offset: 2px;
input[type='checkbox'] {
opacity: 0;
width: 0;
height: 0;
position: absolute;
cursor: pointer;
}
.checkbox-icon {
width: 100%;
height: 100%;
color: var(--primary-foreground-color);
}
&.disabled {
cursor: not-allowed;
}
&.error {
border-color: var(--color-trakt);
}
&.checked {
background-color: var(--primary-accent-color);
}
&:hover, &:focus {
outline-style: solid;
}
}
}

View file

@ -0,0 +1,97 @@
// Copyright (C) 2017-2025 Smart code 203358507
import React, { useCallback, ChangeEvent, KeyboardEvent, RefCallback } from 'react';
import classNames from 'classnames';
import styles from './Checkbox.less';
import Button from '../Button';
import Icon from '@stremio/stremio-icons/react';
type Props = {
ref?: RefCallback<HTMLInputElement>;
name: string;
disabled?: boolean;
checked?: boolean;
className?: string;
label?: string;
link?: string;
href?: string;
onChange?: (props: {
type: string;
checked: boolean;
reactEvent: KeyboardEvent<HTMLInputElement> | ChangeEvent<HTMLInputElement>;
nativeEvent: Event;
}) => void;
error?: string;
};
const Checkbox = React.forwardRef<HTMLInputElement, Props>(({ name, disabled, className, label, href, link, onChange, error, checked }, ref) => {
const handleSelect = useCallback((event: ChangeEvent<HTMLInputElement>) => {
if (!disabled && onChange) {
onChange({
type: 'select',
checked: event.target.checked,
reactEvent: event,
nativeEvent: event.nativeEvent,
});
}
}, [disabled, onChange]);
const onKeyDown = useCallback((event: KeyboardEvent<HTMLInputElement>) => {
if ((event.key === 'Enter' || event.key === ' ') && !disabled) {
onChange && onChange({
type: 'select',
checked: !checked,
reactEvent: event as KeyboardEvent<HTMLInputElement>,
nativeEvent: event.nativeEvent,
});
}
}, [disabled, checked, onChange]);
return (
<div className={classNames(styles['checkbox'], className)}>
<label className={styles['label']} htmlFor={name}>
<div
className={classNames(
styles['checkbox-container'],
{ [styles['checked']]: checked },
{ [styles['disabled']]: disabled },
{ [styles['error']]: error }
)}
role={'checkbox'}
tabIndex={disabled ? -1 : 0}
aria-checked={checked}
onKeyDown={onKeyDown}
>
<input
ref={ref}
id={name}
type={'checkbox'}
checked={checked}
disabled={disabled}
onChange={handleSelect}
className={styles['input']}
/>
{
checked ?
<Icon name={'checkmark'} className={styles['checkbox-icon']} />
: null
}
</div>
<div>
<span>{label}</span>
{' '}
{
href && link ?
<Button className={styles['link']} href={href} target={'_blank'} tabIndex={-1}>
{link}
</Button>
: null
}
</div>
</label>
</div>
);
});
export default Checkbox;

View file

@ -0,0 +1,5 @@
// Copyright (C) 2017-2025 Smart code 203358507
import Checkbox from './Checkbox';
export default Checkbox;

View file

@ -39,7 +39,8 @@ html.active-slider-within {
flex: 1;
height: var(--track-size);
border-radius: var(--track-size);
background-color: var(--overlay-color);
background-color: var(--primary-accent-color);
opacity: 0.2;
}
.track-before {

View file

@ -1,6 +1,7 @@
import AddonDetailsModal from './AddonDetailsModal';
import BottomSheet from './BottomSheet';
import Button from './Button';
import Checkbox from './Checkbox';
import Chips from './Chips';
import ColorInput from './ColorInput';
import ContinueWatchingItem from './ContinueWatchingItem';
@ -31,6 +32,7 @@ export {
AddonDetailsModal,
BottomSheet,
Button,
Checkbox,
Chips,
ColorInput,
ContinueWatchingItem,

View file

@ -95,4 +95,4 @@
&:not(.active):hover {
border-color: var(--overlay-color);
}
}
}

View file

@ -10,6 +10,10 @@
width: 20rem;
padding: 0 1rem;
overflow-y: auto;
@supports (scroll-padding-block-start: 0.15rem) {
scroll-padding-block-start: 0.15rem;
}
}
@media only screen and (max-width: @small) and (orientation: portrait) {
@ -34,4 +38,4 @@
.list {
display: none;
}
}
}

View file

@ -1,56 +0,0 @@
// Copyright (C) 2017-2023 Smart code 203358507
const React = require('react');
const PropTypes = require('prop-types');
const classnames = require('classnames');
const { Button, Toggle } = require('stremio/components');
const styles = require('./styles');
const ConsentToggle = React.forwardRef(({ className, label, link, href, onToggle, ...props }, ref) => {
const toggleOnClick = React.useCallback((event) => {
if (typeof props.onClick === 'function') {
props.onClick(event);
}
if (!event.nativeEvent.togglePrevented && typeof onToggle === 'function') {
onToggle({
type: 'toggle',
reactEvent: event,
nativeEvent: event.nativeEvent
});
}
}, [onToggle, props.onClick]);
const linkOnClick = React.useCallback((event) => {
event.nativeEvent.togglePrevented = true;
}, []);
return (
<Toggle {...props} ref={ref} className={classnames(className, styles['consent-toggle-container'])} onClick={toggleOnClick}>
<div className={styles['label']}>
{label}
{' '}
{
typeof link === 'string' && link.length > 0 && typeof href === 'string' && href.length > 0 ?
<Button className={styles['link']} href={href} target={'_blank'} tabIndex={-1} onClick={linkOnClick}>
{link}
</Button>
:
null
}
</div>
</Toggle>
);
});
ConsentToggle.displayName = 'ConsentToggle';
ConsentToggle.propTypes = {
className: PropTypes.string,
checked: PropTypes.bool,
label: PropTypes.string,
link: PropTypes.string,
href: PropTypes.string,
onToggle: PropTypes.func,
onClick: PropTypes.func
};
module.exports = ConsentToggle;

View file

@ -1,5 +0,0 @@
// Copyright (C) 2017-2023 Smart code 203358507
const ConsentToggle = require('./ConsentToggle');
module.exports = ConsentToggle;

View file

@ -1,43 +0,0 @@
// Copyright (C) 2017-2023 Smart code 203358507
@import (reference) '~@stremio/stremio-colors/less/stremio-colors.less';
:import('~stremio/components/Toggle/styles.less') {
checkbox-icon: icon;
}
.consent-toggle-container {
display: flex;
flex-direction: row;
align-items: center;
padding: 0.5rem 0;
border-radius: var(--border-radius);
&:focus {
outline: none;
background-color: var(--overlay-color);
}
&:global(.checked) {
.label {
opacity: 1;
}
}
.label {
flex: 1;
margin-left: 1rem;
font-size: 0.9rem;
color: var(--primary-foreground-color);
opacity: 0.6;
.link {
font-size: 0.9rem;
color: var(--primary-accent-color);
&:hover {
text-decoration: underline;
}
}
}
}

View file

@ -8,9 +8,8 @@ const { default: Icon } = require('@stremio/stremio-icons/react');
const { Modal, useRouteFocused } = require('stremio-router');
const { useServices } = require('stremio/services');
const { useBinaryState } = require('stremio/common');
const { Button, Image } = require('stremio/components');
const { Button, Image, Checkbox } = require('stremio/components');
const CredentialsTextInput = require('./CredentialsTextInput');
const ConsentToggle = require('./ConsentToggle');
const PasswordResetModal = require('./PasswordResetModal');
const useFacebookLogin = require('./useFacebookLogin');
const styles = require('./styles');
@ -308,30 +307,27 @@ const Intro = ({ queryParams }) => {
onChange={confirmPasswordOnChange}
onSubmit={confirmPasswordOnSubmit}
/>
<ConsentToggle
<Checkbox
ref={termsRef}
className={styles['consent-toggle']}
label={'I have read and agree with the Stremio'}
link={'Terms and conditions'}
href={'https://www.stremio.com/tos'}
checked={state.termsAccepted}
onToggle={toggleTermsAccepted}
onChange={toggleTermsAccepted}
/>
<ConsentToggle
<Checkbox
ref={privacyPolicyRef}
className={styles['consent-toggle']}
label={'I have read and agree with the Stremio'}
link={'Privacy Policy'}
href={'https://www.stremio.com/privacy'}
checked={state.privacyPolicyAccepted}
onToggle={togglePrivacyPolicyAccepted}
onChange={togglePrivacyPolicyAccepted}
/>
<ConsentToggle
<Checkbox
ref={marketingRef}
className={styles['consent-toggle']}
label={'I agree to receive marketing communications from Stremio'}
checked={state.marketingAccepted}
onToggle={toggleMarketingAccepted}
onChange={toggleMarketingAccepted}
/>
</React.Fragment>
: