Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prettier poll result #245

Merged
merged 16 commits into from
Apr 17, 2024
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"homepage": "/playback/presentation/2.3",
"dependencies": {
"@tldraw/tldraw": "^2.0.0-alpha.18",
"bowser": "^2.11.0",
"classnames": "^2.3.1",
"darkreader": "^4.9.46",
"linkify-react": "^3.0.4",
Expand Down
4 changes: 4 additions & 0 deletions src/components/chat/messages/system/poll/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
padding-bottom: $padding-small;
}

.poll-pads {
visibility: hidden;
}

.poll-bar {
color: var(--poll-bar-color);
}
Expand Down
16 changes: 15 additions & 1 deletion src/components/chat/messages/system/poll/result.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import {
getBar,
getPads,
getPercentage,
} from 'utils/data';
import { isEmpty } from 'utils/data/validators';
Expand All @@ -17,12 +18,17 @@ const defaultProps = {
responders: 0,
};

const getDigits = (n) => { return n.toString().length; };

const Result = ({
answers,
responders,
}) => {
if (isEmpty(answers)) return null;

const answersDigits = getDigits(answers.length);
const maxVotes = Math.max(...answers.map((item) => { return item.numVotes; }));
const maxVotesDigits = getDigits(maxVotes);
return (
<div className="poll-result">
{answers.map((item) => {
Expand All @@ -35,7 +41,15 @@ const Result = ({

return(
<div className="poll-label">
{id + 1}: {numVotes} <span className="poll-bar">{getBar(percentage)}</span> {percentage}%
{id + 1}
<span className="poll-pads">
{getPads(answersDigits - getDigits(id+1))}
</span>
: {numVotes}
<span className="poll-pads">
{getPads(maxVotesDigits - getDigits(numVotes)) + ' '}
</span>
<span className="poll-bar">{getBar(percentage)}</span> {percentage}%
</div>
);
})}
Expand Down
29 changes: 29 additions & 0 deletions src/utils/browserInfo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Bowser from 'bowser';

const BOWSER_RESULTS = Bowser.parse(window.navigator.userAgent);

const isChrome = BOWSER_RESULTS.browser.name === 'Chrome';
const isSafari = BOWSER_RESULTS.browser.name === 'Safari';
const isEdge = BOWSER_RESULTS.browser.name === 'Microsoft Edge';
const isIe = BOWSER_RESULTS.browser.name === 'Internet Explorer';
const isFirefox = BOWSER_RESULTS.browser.name === 'Firefox';

const browserName = BOWSER_RESULTS.browser.name;
const versionNumber = BOWSER_RESULTS.browser.version;

const isValidSafariVersion = Bowser.getParser(window.navigator.userAgent).satisfies({
safari: '>12',
});

const browserInfo = {
isChrome,
isSafari,
isEdge,
isIe,
isFirefox,
browserName,
versionNumber,
isValidSafariVersion,
};

export default browserInfo;
21 changes: 21 additions & 0 deletions src/utils/data/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {
} from 'utils/data/validators';
import hash from 'utils/hash';
import { getMediaPath } from 'utils/params';
import browserInfo from 'utils/browserInfo';
import deviceInfo from 'utils/deviceInfo';

const buildFileURL = (file, recordId = null) => {
if (!ROUTER) return file;
Expand All @@ -40,6 +42,8 @@ const FULL_BLOCK = '█';
const LEFT_HALF_BLOCK = '▌';
const RIGHT_HALF_BLOCK = '▐';
const EMPTY_BLOCK = '-';
const FIGURE_SPACE = ' ';
const EN_SPACE = ' '
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just out of curiosity, what is the difference between the EN and the Figure spaces?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After some experiment, I've found FIGURE_SPACE does not work for Firefox and EN_SPACE is better. I don't know the difference in detail, but by definition EN_SPACE is 1/2 em. And FIGURE_SPACE should have the same size of digit zero of a fixed font. However, there are somebody saying that it's not guaranteed....


const getBar = (percentage) => {
const p = parseInt(percentage);
Expand All @@ -63,6 +67,22 @@ const getBar = (percentage) => {
return bar;
};

const getPads = (n) => {
if (deviceInfo.osName === "Linux") {
// Note the conditional branch below could be the other way around
// i.e. FIGURE_SPACE for Firefox and EN_SPACE for Chrome
// depending on locale.
// See https://github.com/bigbluebutton/bbb-playback/pull/245 .
if (browserInfo.isChrome) {
return EN_SPACE.repeat(n);
} else if (browserInfo.isFirefox) {
return FIGURE_SPACE.repeat(n);
}
} else {
return FULL_BLOCK.repeat(n);
}
}

const getCurrentContent = (time) => {
const {
SCREENSHARE,
Expand Down Expand Up @@ -180,6 +200,7 @@ export {
buildFileURL,
getAvatarStyle,
getBar,
getPads,
getCurrentContent,
getCurrentDataIndex,
getCurrentDataInterval,
Expand Down
34 changes: 34 additions & 0 deletions src/utils/deviceInfo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import Bowser from 'bowser';

const BOWSER_RESULTS = Bowser.parse(window.navigator.userAgent);

const isPhone = BOWSER_RESULTS.platform.type === 'mobile';
// we need a 'hack' to correctly detect ipads with ios > 13
const isTablet = BOWSER_RESULTS.platform.type === 'tablet' || (BOWSER_RESULTS.os.name === 'macOS' && window.navigator.maxTouchPoints > 0);
const isMobile = isPhone || isTablet;
const hasMediaDevices = !!navigator.mediaDevices;
const osName = BOWSER_RESULTS.os.name;
const osVersion = BOWSER_RESULTS.os.version;
const isIos = osName === 'iOS';
const isMacos = osName === 'macOS';
const isIphone = !!(window.navigator.userAgent.match(/iPhone/i));

const SUPPORTED_IOS_VERSION = 12.2;
const isIosVersionSupported = () => parseFloat(osVersion) >= SUPPORTED_IOS_VERSION;

const isPortrait = () => window.innerHeight > window.innerWidth;

const deviceInfo = {
isTablet,
isPhone,
isMobile,
hasMediaDevices,
osName,
isPortrait,
isIos,
isMacos,
isIphone,
isIosVersionSupported,
};

export default deviceInfo;