Skip to content

Commit

Permalink
Revert "Revert "Add loading Animation to Most used Language card (anu…
Browse files Browse the repository at this point in the history
  • Loading branch information
rickstaa authored Jan 16, 2023
1 parent ad9db67 commit 06a2a78
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 29 deletions.
2 changes: 2 additions & 0 deletions api/top-langs.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export default async (req, res) => {
locale,
border_radius,
border_color,
disable_animations,
} = req.query;
res.setHeader("Content-Type", "image/svg+xml");

Expand Down Expand Up @@ -75,6 +76,7 @@ export default async (req, res) => {
border_radius,
border_color,
locale: locale ? locale.toLowerCase() : null,
disable_animations: parseBoolean(disable_animations),
}),
);
} catch (err) {
Expand Down
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ You can provide multiple comma-separated values in the bg_color option to render
- `langs_count` - Show more languages on the card, between 1-10 _(number)_. Default `5`.
- `exclude_repo` - Exclude specified repositories _(Comma-separated values)_. Default: `[] (blank array)`.
- `custom_title` - Sets a custom title for the card _(string)_. Default `Most Used Languages`.
- `disable_animations` - Disables all animations in the card _(boolean)_. Default: `false`.

> **Warning**
> Language names should be URI-escaped, as specified in [Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding)
Expand Down
82 changes: 61 additions & 21 deletions src/cards/top-languages-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,46 +39,53 @@ const getLongestLang = (arr) =>
* Creates a node to display usage of a programming language in percentage
* using text and a horizontal progress bar.
*
* @param {object[]} props Function properties.
* @param {object} props Function properties.
* @param {number} props.width The card width
* @param {string} props.name Name of the programming language.
* @param {string} props.color Color of the programming language.
* @param {string} props.progress Usage of the programming language in percentage.
* @param {number} props.index Index of the programming language.
* @returns {string} Programming language SVG node.
*/
const createProgressTextNode = ({ width, color, name, progress }) => {
const createProgressTextNode = ({ width, color, name, progress, index }) => {
const staggerDelay = (index + 3) * 150;
const paddingRight = 95;
const progressTextX = width - paddingRight + 10;
const progressWidth = width - paddingRight;

return `
<text data-testid="lang-name" x="2" y="15" class="lang-name">${name}</text>
<text x="${progressTextX}" y="34" class="lang-name">${progress}%</text>
${createProgressNode({
x: 0,
y: 25,
color,
width: progressWidth,
progress,
progressBarBackgroundColor: "#ddd",
})}
<g class="stagger" style="animation-delay: ${staggerDelay}ms">
<text data-testid="lang-name" x="2" y="15" class="lang-name">${name}</text>
<text x="${progressTextX}" y="34" class="lang-name">${progress}%</text>
${createProgressNode({
x: 0,
y: 25,
color,
width: progressWidth,
progress,
progressBarBackgroundColor: "#ddd",
delay: staggerDelay + 300,
})}
</g>
`;
};

/**
* Creates a text only node to display usage of a programming language in percentage.
*
* @param {object[]} props Function properties.
* @param {object} props Function properties.
* @param {Lang} props.lang Programming language object.
* @param {number} props.totalSize Total size of all languages.
* @param {number} props.index Index of the programming language.
* @returns {string} Compact layout programming language SVG node.
*/
const createCompactLangNode = ({ lang, totalSize }) => {
const createCompactLangNode = ({ lang, totalSize, index }) => {
const percentage = ((lang.size / totalSize) * 100).toFixed(2);
const staggerDelay = (index + 3) * 150;
const color = lang.color || "#858585";

return `
<g>
<g class="stagger" style="animation-delay: ${staggerDelay}ms">
<circle cx="5" cy="6" r="5" fill="${color}" />
<text data-testid="lang-name" x="15" y="10" class='lang-name'>
${lang.name} ${percentage}%
Expand All @@ -104,7 +111,6 @@ const createLanguageTextNode = ({ langs, totalSize }) => {
createCompactLangNode({
lang,
totalSize,
// @ts-ignore
index,
}),
);
Expand Down Expand Up @@ -134,12 +140,13 @@ const createLanguageTextNode = ({ langs, totalSize }) => {
*/
const renderNormalLayout = (langs, width, totalLanguageSize) => {
return flexLayout({
items: langs.map((lang) => {
items: langs.map((lang, index) => {
return createProgressTextNode({
width: width,
width,
name: lang.name,
color: lang.color || DEFAULT_LANG_COLOR,
progress: ((lang.size / totalLanguageSize) * 100).toFixed(2),
index,
});
}),
gap: 40,
Expand Down Expand Up @@ -187,7 +194,7 @@ const renderCompactLayout = (langs, width, totalLanguageSize) => {

return `
<mask id="rect-mask">
<rect x="0" y="0" width="${offsetWidth}" height="8" fill="white" rx="5" />
<rect x="0" y="0" width="${offsetWidth}" height="8" fill="white" rx="5"/>
</mask>
${compactProgressBar}
Expand Down Expand Up @@ -276,6 +283,7 @@ const renderTopLanguages = (topLangs, options = {}) => {
langs_count = DEFAULT_LANGS_COUNT,
border_radius,
border_color,
disable_animations,
} = options;

const i18n = new I18n({
Expand Down Expand Up @@ -324,11 +332,43 @@ const renderTopLanguages = (topLangs, options = {}) => {
colors,
});

card.disableAnimations();
if (disable_animations) card.disableAnimations();

card.setHideBorder(hide_border);
card.setHideTitle(hide_title);
card.setCSS(
`.lang-name { font: 400 11px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${colors.textColor} }`,
`
@keyframes slideInAnimation {
from {
width: 0;
}
to {
width: calc(100%-100px);
}
}
@keyframes growWidthAnimation {
from {
width: 0;
}
to {
width: 100%;
}
}
.lang-name {
font: 400 11px "Segoe UI", Ubuntu, Sans-Serif;
fill: ${colors.textColor};
}
.stagger {
opacity: 0;
animation: fadeInAnimation 0.3s ease-in-out forwards;
}
#rect-mask rect{
animation: slideInAnimation 1s ease-in-out forwards;
}
.lang-progress{
animation: growWidthAnimation 0.6s ease-in-out forwards;
}
`,
);

return card.render(`
Expand Down
1 change: 1 addition & 0 deletions src/cards/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export type TopLangOptions = CommonOptions & {
layout: "compact" | "normal";
custom_title: string;
langs_count: number;
disable_animations: boolean;
};

type WakaTimeOptions = CommonOptions & {
Expand Down
19 changes: 11 additions & 8 deletions src/common/createProgressNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { clampValue } from "./utils.js";
* @param {string} createProgressNodeParams.color Progress color.
* @param {string} createProgressNodeParams.progress Progress value.
* @param {string} createProgressNodeParams.progressBarBackgroundColor Progress bar bg color.
* @param {number} createProgressNodeParams.delay Delay before animation starts.
* @returns {string} Progress node.
*/
const createProgressNode = ({
Expand All @@ -19,20 +20,22 @@ const createProgressNode = ({
color,
progress,
progressBarBackgroundColor,
delay,
}) => {
const progressPercentage = clampValue(progress, 2, 100);

return `
<svg width="${width}" x="${x}" y="${y}">
<rect rx="5" ry="5" x="0" y="0" width="${width}" height="8" fill="${progressBarBackgroundColor}"></rect>
<rect
height="8"
fill="${color}"
rx="5" ry="5" x="0" y="0"
data-testid="lang-progress"
width="${progressPercentage}%"
>
</rect>
<svg data-testid="lang-progress" width="${progressPercentage}%">
<rect
height="8"
fill="${color}"
rx="5" ry="5" x="0" y="0"
class="lang-progress"
style="animation-delay: ${delay}ms;"
/>
</svg>
</svg>
`;
};
Expand Down

0 comments on commit 06a2a78

Please sign in to comment.