SpotifyControls: improve time formatting for tracks over an hour
This commit is contained in:
parent
0f10b57065
commit
a040c8dbe6
4 changed files with 41 additions and 40 deletions
|
|
@ -20,6 +20,7 @@ import { definePluginSettings } from "@api/Settings";
|
|||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { useTimer } from "@utils/react";
|
||||
import { formatDuration } from "@utils/text";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { React } from "@webpack/common";
|
||||
|
||||
|
|
@ -39,33 +40,10 @@ const settings = definePluginSettings({
|
|||
label: "30d 23h 00m 42s",
|
||||
value: "human"
|
||||
}
|
||||
]
|
||||
] as const
|
||||
}
|
||||
});
|
||||
|
||||
function formatDuration(ms: number) {
|
||||
// here be dragons (moment fucking sucks)
|
||||
const human = settings.store.format === "human";
|
||||
|
||||
const format = (n: number) => human ? n : n.toString().padStart(2, "0");
|
||||
const unit = (s: string) => human ? s : "";
|
||||
const delim = human ? " " : ":";
|
||||
|
||||
// thx copilot
|
||||
const d = Math.floor(ms / 86400000);
|
||||
const h = Math.floor((ms % 86400000) / 3600000);
|
||||
const m = Math.floor(((ms % 86400000) % 3600000) / 60000);
|
||||
const s = Math.floor((((ms % 86400000) % 3600000) % 60000) / 1000);
|
||||
|
||||
let res = "";
|
||||
if (d) res += `${d}d `;
|
||||
if (h || res) res += `${format(h)}${unit("h")}${delim}`;
|
||||
if (m || res || !human) res += `${format(m)}${unit("m")}${delim}`;
|
||||
res += `${format(s)}${unit("s")}`;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default definePlugin({
|
||||
|
|
@ -94,7 +72,7 @@ export default definePlugin({
|
|||
|
||||
return (
|
||||
<p style={{ margin: 0, fontFamily: "var(--font-code)" }}>
|
||||
{formatDuration(time)}
|
||||
{formatDuration(time, settings.store.format === "human")}
|
||||
</p>
|
||||
);
|
||||
}, { noop: true }),
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import PermissionsViewerPlugin from "@plugins/permissionsViewer";
|
|||
import openRolesAndUsersPermissionsModal from "@plugins/permissionsViewer/components/RolesAndUsersPermissions";
|
||||
import { sortPermissionOverwrites } from "@plugins/permissionsViewer/utils";
|
||||
import { classes } from "@utils/misc";
|
||||
import { formatDuration } from "@utils/text";
|
||||
import { formatDurationVerbose } from "@utils/text";
|
||||
import type { Channel, RoleOrUserPermission } from "@vencord/discord-types";
|
||||
import { findByPropsLazy, findComponentByCodeLazy, findCssClassesLazy } from "@webpack";
|
||||
import { EmojiStore, FluxDispatcher, GuildMemberStore, GuildStore, Parser, PermissionsBits, PermissionStore, SnowflakeUtils, Text, Timestamp, Tooltip, useEffect, useState } from "@webpack/common";
|
||||
|
|
@ -204,11 +204,11 @@ function HiddenChannelLockScreen({ channel }: { channel: Channel; }) {
|
|||
<Text variant="text-md/normal">Last message pin: <Timestamp timestamp={new Date(lastPinTimestamp)} /></Text>
|
||||
}
|
||||
{(rateLimitPerUser ?? 0) > 0 &&
|
||||
<Text variant="text-md/normal">Slowmode: {formatDuration(rateLimitPerUser!, "seconds")}</Text>
|
||||
<Text variant="text-md/normal">Slowmode: {formatDurationVerbose(rateLimitPerUser!, "seconds")}</Text>
|
||||
}
|
||||
{(defaultThreadRateLimitPerUser ?? 0) > 0 &&
|
||||
<Text variant="text-md/normal">
|
||||
Default thread slowmode: {formatDuration(defaultThreadRateLimitPerUser!, "seconds")}
|
||||
Default thread slowmode: {formatDurationVerbose(defaultThreadRateLimitPerUser!, "seconds")}
|
||||
</Text>
|
||||
}
|
||||
{((channel.isGuildVoice() || channel.isGuildStageVoice()) && bitrate != null) &&
|
||||
|
|
@ -223,7 +223,7 @@ function HiddenChannelLockScreen({ channel }: { channel: Channel; }) {
|
|||
{(defaultAutoArchiveDuration ?? 0) > 0 &&
|
||||
<Text variant="text-md/normal">
|
||||
Default inactivity duration before archiving {channel.isForumChannel() ? "posts" : "threads"}:
|
||||
{" " + formatDuration(defaultAutoArchiveDuration!, "minutes")}
|
||||
{" " + formatDurationVerbose(defaultAutoArchiveDuration!, "minutes")}
|
||||
</Text>
|
||||
}
|
||||
{defaultForumLayout != null &&
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import { debounce } from "@shared/debounce";
|
|||
import { classNameFactory } from "@utils/css";
|
||||
import { copyWithToast, openImageModal } from "@utils/discord";
|
||||
import { classes } from "@utils/misc";
|
||||
import { formatDuration } from "@utils/text";
|
||||
import { ContextMenuApi, FluxDispatcher, Menu, React, useEffect, useState, useStateFromStores } from "@webpack/common";
|
||||
|
||||
import { settings } from ".";
|
||||
|
|
@ -34,13 +35,6 @@ import { SpotifyStore, Track } from "./SpotifyStore";
|
|||
|
||||
const cl = classNameFactory("vc-spotify-");
|
||||
|
||||
function msToHuman(ms: number) {
|
||||
const minutes = ms / 1000 / 60;
|
||||
const m = Math.floor(minutes);
|
||||
const s = Math.floor((minutes - m) * 60);
|
||||
return `${m.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}`;
|
||||
}
|
||||
|
||||
function Svg(path: string, label: string) {
|
||||
return () => (
|
||||
<svg
|
||||
|
|
@ -193,7 +187,7 @@ function SpotifySeekBar() {
|
|||
className={cl("progress-time") + " " + cl("time-left")}
|
||||
aria-label="Progress"
|
||||
>
|
||||
{msToHuman(position)}
|
||||
{formatDuration(position)}
|
||||
</Span>
|
||||
<SeekBar
|
||||
initialValue={position}
|
||||
|
|
@ -201,7 +195,7 @@ function SpotifySeekBar() {
|
|||
maxValue={duration}
|
||||
onValueChange={onChange}
|
||||
asValueChanges={onChange}
|
||||
onValueRender={msToHuman}
|
||||
onValueRender={formatDuration}
|
||||
/>
|
||||
<Span
|
||||
size="xs"
|
||||
|
|
@ -209,7 +203,7 @@ function SpotifySeekBar() {
|
|||
className={cl("progress-time") + " " + cl("time-right")}
|
||||
aria-label="Total Duration"
|
||||
>
|
||||
{msToHuman(duration)}
|
||||
{formatDuration(duration)}
|
||||
</Span>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { isTruthy } from "./guards";
|
||||
|
||||
// Utils for readable text transformations eg: `toTitle(fromKebab())`
|
||||
|
||||
// Case style to words
|
||||
|
|
@ -51,7 +53,7 @@ function getUnitStr(unit: Units, isOne: boolean, short: boolean) {
|
|||
* @param unit The unit the time is on
|
||||
* @param short Whether to use short units like "d" instead of "days"
|
||||
*/
|
||||
export function formatDuration(time: number, unit: Units, short: boolean = false) {
|
||||
export function formatDurationVerbose(time: number, unit: Units, short: boolean = false) {
|
||||
const { moment } = require("@webpack/common") as typeof import("@webpack/common");
|
||||
const dur = moment.duration(time, unit);
|
||||
|
||||
|
|
@ -93,6 +95,33 @@ export function formatDuration(time: number, unit: Units, short: boolean = false
|
|||
return res.length ? res : `0 ${getUnitStr(unit, false, short)}`;
|
||||
}
|
||||
|
||||
export function formatDuration(ms: number, human = false) {
|
||||
const DAY = 86_400_000;
|
||||
const HOUR = 3_600_000;
|
||||
const MINUTE = 60_000;
|
||||
|
||||
const days = Math.floor(ms / DAY);
|
||||
const hours = Math.floor((ms % DAY) / HOUR);
|
||||
const minutes = Math.floor((ms % HOUR) / MINUTE);
|
||||
const seconds = Math.floor((ms % MINUTE) / 1000);
|
||||
|
||||
const pad = (n: number) => human ? n : n.toString().padStart(2, "0");
|
||||
const unit = (s: string) => human ? s : "";
|
||||
|
||||
const showDays = days !== 0;
|
||||
const showHours = showDays || hours !== 0;
|
||||
const showMinutes = showHours || minutes !== 0 || !human;
|
||||
|
||||
const duration = [
|
||||
showHours && `${pad(hours)}${unit("h")}`,
|
||||
showMinutes && `${pad(minutes)}${unit("m")}`,
|
||||
`${pad(seconds)}${unit("s")}`
|
||||
].filter(isTruthy).join(human ? " " : ":");
|
||||
|
||||
const prefix = showDays ? `${days}d ` : "";
|
||||
return prefix + duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join an array of strings in a human readable way (1, 2 and 3)
|
||||
* @param elements Elements
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue