Skip to content

Commit

Permalink
New services (#40)
Browse files Browse the repository at this point in the history
* move all services data to `services.data` file

* support `X` & `WhatsApp`

* improve loading cover

* update `CHANGELOG.md`

* `CHANGELOG.md` updated
  • Loading branch information
F-Shahali authored Oct 17, 2024
1 parent d745908 commit 7600705
Show file tree
Hide file tree
Showing 12 changed files with 181 additions and 86 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]
### Added
- Support `X`
- Support `WhatsApp`
- Support multi parameters
- Handle url encoding
### Changed
- Move all services data to `services.data` file
- Improve loading-cover animation
- Move `build` & `version_check` steps to `github runners`
- `AUTHORS.md` updated
## [0.2] - 2024-09-16
Expand Down
1 change: 1 addition & 0 deletions src/Assets/icons/services/whatsapp.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/Assets/icons/services/x.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
88 changes: 88 additions & 0 deletions src/Components/Loader/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
.loader-layout {
display: inline-block;
position: relative;
width: 100px;
height: 100px;

.loading-circle {
@apply bg-primary absolute;
width: 16px;
height: 16px;
border-radius: 50%;
animation: loader-animation 1s linear infinite;

&:nth-child(1) {
animation-delay: 0s;
transform: rotate(320deg);
opacity: 0.2222222222222222;
top: 75%;
left: 44%;
}

&:nth-child(2) {
animation-delay: -0.1122334455667789s;
transform: rotate(280);
opacity: 0.3333333333333333;
top: 67.98133329356934%;
left: 63.28362829059617%;
}

&:nth-child(3) {
transform: rotate(239.99999999999997deg);
animation-delay: -0.2244668911335578s;
opacity: 0.4444444444444444;
top: 50.20944533000791%;
left: 73.54423259036625%;
}
&:nth-child(4) {
animation-delay: -0.3367003367003367s;
transform: rotate(200deg);
opacity: 0.5555555555555556;
top: 30.00000000000001%;
left: 69.98076211353316%;
}
&:nth-child(5) {
animation-delay: -0.4489337822671156s;
transform: rotate(160deg);
opacity: 0.6666666666666666;
top: 16.80922137642275%;
left: 54.260604299770065%;
}
&:nth-child(6) {
animation-delay: -0.5611672278338945s;
transform: rotate(119.99999999999999deg);
opacity: 0.7777777777777778;
top: 16.809221376422748%;
left: 33.73939570022994%;
}
&:nth-child(7) {
animation-delay: -0.6734006734006734s;
transform: rotate(80deg);
opacity: 0.7777777777777778;
top: 29.999999999999986%;
left: 18.019237886466847%;
}
&:nth-child(8) {
animation-delay: -0.7856341189674523s;
transform: rotate(40deg);
opacity: 0.8888888888888888;
top: 50.20944533000789%;
left: 14.455767409633758%;
}
&:nth-child(9) {
animation-delay: -0.8978675645342312s;
transform: rotate(0deg);
opacity: 1;
top: 67.98133329356934%;
left: 24.716371709403813%;
}
}
}
@keyframes loader-animation {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
13 changes: 13 additions & 0 deletions src/Components/Loader/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import './index.scss';

const Loader = () => {
return (
<div className={'loader-layout'}>
{[...Array(9)].map((_, index) => (
<div key={index} className='loading-circle' />
))}
</div>
);
};

export default Loader;
4 changes: 2 additions & 2 deletions src/Components/LoadingCover.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { ReactComponent as Loader } from '@assets/icons/loader.svg';
import Loader from './Loader';

type LoadingCoverProps = { className?: string };

const LoadingCover: FC<LoadingCoverProps> = ({ className = '' }) => (
<div className={'loading-cover ' + className}>
<Loader className={'loading-cover-loader ' + className} />
<Loader />
</div>
);

Expand Down
48 changes: 48 additions & 0 deletions src/Data/services.data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import Email from '@assets/icons/services/email.svg';
import Gmail from '@assets/icons/services/gmail.svg';
import Telegram from '@assets/icons/services/telegram.svg';
import Whatsapp from '@assets/icons/services/whatsapp.svg';
import X from '@assets/icons/services/x.svg';

export const services_url = (url: string, subject?: string): { [key: string]: string } => {
return {
email: `mailto:?subject=${subject}&body=${url}`,
gmail: `https://mail.google.com/mail/u/0/?ui=2&fs=1&tf=cm&su=${subject}&body=${url}`,
telegram: `https://telegram.me/share/url?url=${url}&text=${subject}`,
x: `https://x.com/intent/post?url=${url}&text=${subject}`,
whatsapp: `https://api.whatsapp.com/send?text=${subject}%20${url}`,
};
};

export const Services = [
{
title: 'email',
icon: Email,
iconUrl: 'https://github.com/openscilab/mybutton/raw/main/src/Assets/icons/services/email.svg',
bg: '#888990',
},
{
title: 'gmail',
icon: Gmail,
iconUrl: 'https://github.com/openscilab/mybutton/raw/main/src/Assets/icons/services/gmail.svg',
bg: '#EA4335',
},
{
title: 'telegram',
icon: Telegram,
iconUrl: 'https://github.com/openscilab/mybutton/raw/main/src/Assets/icons/services/telegram.svg',
bg: '#2CA5E0',
},
{
title: 'x',
icon: X,
iconUrl: 'https://github.com/openscilab/mybutton/raw/main/src/Assets/icons/services/x.svg',
bg: '#1A1A1A',
},
{
title: 'whatsapp',
icon: Whatsapp,
iconUrl: 'https://github.com/openscilab/mybutton/raw/main/src/Assets/icons/services/whatsapp.svg',
bg: '#12AF0A',
},
];
11 changes: 5 additions & 6 deletions src/Views/Layout/ShareModal/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,19 @@
@apply w-full overflow-y-auto mt-8;

.rs-col {
@apply md:flex md:justify-center;
@apply md:flex md:justify-center sm:mb-2;
}
.service-container {
@apply cursor-pointer px-1 md:px-2 flex items-center rounded-lg transition-colors duration-300;
width: fit-content;
height: fit-content;
@apply cursor-pointer px-2 flex items-center rounded-lg transition-colors duration-300 w-32;

.service-logo {
@apply rounded-md;
border-radius: 4px;
width: fit-content;
height: fit-content;
padding: 0.03rem;

img {
@apply w-5 h-5 sm:w-8 sm:h-8;
@apply w-7 h-7 sm:w-8 sm:h-8;
}
}

Expand Down
34 changes: 3 additions & 31 deletions src/Views/Layout/ShareModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import './index.scss';
import { useState } from 'react';
import useStore from '@src/Tools/Store/useStore';
import { CONFIG } from '@src/App/Config/constants';
import Email from '@assets/icons/services/email.svg';
import Gmail from '@assets/icons/services/gmail.svg';
import Telegram from '@assets/icons/services/telegram.svg';
import { Services, services_url } from '@src/Data/services.data';
import EditableInput from '@src/Components/EditableInput/EditableInput';
import { Col, Modal, Radio, RadioGroup, Row, Tooltip, Whisper } from 'rsuite';
import { setOpenShareModal, useLocalCache } from '@src/Tools/Store/slices/LocalCacheSlice';
Expand Down Expand Up @@ -33,32 +31,6 @@ const ShareModal = () => {
return `${CONFIG.FRONT_DOMAIN}/?path=share&service=${service_title}&subject=${subject}&link=${url}`;
};

// ? ---------------------- Var -------------------------------
const services_url = (url: string): { [key: string]: string } => {
return {
email: `mailto:?subject=${subject}&body=${url}`,
gmail: `https://mail.google.com/mail/u/0/?ui=2&fs=1&tf=cm&su=${subject}&body=${url}`,
telegram: `https://telegram.me/share/url?url=${url}&text=${subject}`,
};
};

const Services = [
{
title: 'email',
icon: Email,
bg: '#888990',
},
{
title: 'gmail',
icon: Gmail,
bg: '#EA4335',
},
{
title: 'telegram',
icon: Telegram,
bg: '#2CA5E0',
},
];
// --------------------------------------------------------------
return (
<Modal
Expand Down Expand Up @@ -120,10 +92,10 @@ const ShareModal = () => {
const validated_url = urlValidation(url);
const href =
shareMode === 'direct'
? services_url(validated_url)[service.title]
? services_url(validated_url, subject)[service.title]
: getShareLink(service.title, validated_url);
return (
<Col xs={8} key={i}>
<Col xs={12} sm={8} key={i}>
<div
className='service-container'
onClick={() => {
Expand Down
8 changes: 6 additions & 2 deletions src/Views/Pages/GetButton/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@
.services-list {
@apply overflow-y-auto;

.rs-col {
@apply sm:mb-2;
}

.service-radio {
.rs-radio-wrapper {
top: auto;
Expand All @@ -182,12 +186,12 @@
@apply flex items-center;

.service-logo {
@apply rounded-md;
border-radius: 4px;
width: fit-content;
height: fit-content;

img {
@apply w-6 h-6 sm:w-8 sm:h-8;
@apply w-7 h-7 sm:w-8 sm:h-8;
}
}

Expand Down
41 changes: 6 additions & 35 deletions src/Views/Pages/GetButton/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ import Service from '@src/Components/Service';
import useWindow from '@src/Tools/Hooks/useWindow';
import { useData } from '@src/Tools/Hooks/useData';
import { CONFIG } from '@src/App/Config/constants';
import Email from '@assets/icons/services/email.svg';
import Gmail from '@assets/icons/services/gmail.svg';
import SyntaxHighlighter from 'react-syntax-highlighter';
import { copyToClipboard } from '@src/Tools/Utils/React';
import Telegram from '@assets/icons/services/telegram.svg';
import { Services, services_url } from '@src/Data/services.data';
import EditableInput from '@src/Components/EditableInput/EditableInput';
import { lightfair } from 'react-syntax-highlighter/dist/esm/styles/hljs';
import { ReactComponent as Clone } from '@assets/icons/clone-regular.svg';
Expand Down Expand Up @@ -54,12 +52,13 @@ const GetButton = () => {
}

const validated_url = urlValidation(temp.url || '');
const selected = Services(validated_url).filter(service => selectedServices.includes(service.title));
const selected = Services.filter(service => selectedServices.includes(service.title));
const urls = services_url(validated_url, temp.subject);

const buttons = (
<div className='flex-center'>
{selected.map((service, i) => {
const href = temp.shareMode === 'direct' ? service.url : getShareLink(service.title, validated_url);
const href = temp.shareMode === 'direct' ? urls[service.title] : getShareLink(service.title, validated_url);
return (
<a href={href} target='_blank' rel='noreferrer' key={i}>
<img
Expand All @@ -79,7 +78,7 @@ const GetButton = () => {
const code = ` <div>
${selected
.map(service => {
const href = temp.shareMode === 'direct' ? service.url : getShareLink(service.title, validated_url);
const href = temp.shareMode === 'direct' ? urls[service.title] : getShareLink(service.title, validated_url);
return `<a href="${href}" target="_blank"><img src="${service.iconUrl}" width="32" height="32" style="background-color:${service.bg}; border-radius:4px"/></a>`;
})
.join(`\n `)}
Expand All @@ -99,34 +98,6 @@ const GetButton = () => {
return encodeURIComponent(validated);
};

// ? ---------------------- Var -------------------------------

const Services = (url: string = '') => {
return [
{
title: 'email',
icon: Email,
iconUrl: 'https://github.com/openscilab/mybutton/raw/main/src/Assets/icons/services/email.svg',
bg: '#888990',
url: `mailto:?subject=${temp.subject}&body=${url}`,
},
{
title: 'gmail',
icon: Gmail,
iconUrl: 'https://github.com/openscilab/mybutton/raw/main/src/Assets/icons/services/gmail.svg',
bg: '#EA4335',
url: `https://mail.google.com/mail/u/0/?ui=2&fs=1&tf=cm&su=${temp.subject}&body=${url}`,
},
{
title: 'telegram',
icon: Telegram,
iconUrl: 'https://github.com/openscilab/mybutton/raw/main/src/Assets/icons/services/telegram.svg',
bg: '#2CA5E0',
url: `https://telegram.me/share/url?url=${url}&text=${temp.subject}`,
},
];
};

// ? ------------------------------ useEffect -------------------------------
useEffect(() => {
if (temp.showCode) getCode();
Expand Down Expand Up @@ -237,7 +208,7 @@ const GetButton = () => {
<Modal.Body>
<div className='services-list'>
<Row>
{Services().map((service, i) => {
{Services.map((service, i) => {
const checked = selectedServices.includes(service.title);
return (
<Col xs={12} sm={8} key={i}>
Expand Down
Loading

0 comments on commit 7600705

Please sign in to comment.