Merge branch 'master' into issue-407-text-style-messages
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import { Separator } from "@app/components/UI/Seperator";
|
import { Separator } from "@app/components/UI/Seperator";
|
||||||
import { H5 } from "@app/components/UI/Typography/H5.tsx";
|
import { H5 } from "@app/components/UI/Typography/H5.tsx";
|
||||||
import { Subtle } from "@app/components/UI/Typography/Subtle.tsx";
|
import { Subtle } from "@app/components/UI/Typography/Subtle.tsx";
|
||||||
|
import { formatQuantity } from "@app/core/utils/string";
|
||||||
import { Avatar } from "@components/UI/Avatar";
|
import { Avatar } from "@components/UI/Avatar";
|
||||||
import { Mono } from "@components/generic/Mono.tsx";
|
import { Mono } from "@components/generic/Mono.tsx";
|
||||||
import { TimeAgo } from "@components/generic/Table/tmp/TimeAgo.tsx";
|
import { TimeAgo } from "@components/generic/Table/tmp/TimeAgo.tsx";
|
||||||
@@ -132,7 +133,12 @@ export const NodeDetail = ({ node }: NodeDetailProps) => {
|
|||||||
className="ml-2 mr-1"
|
className="ml-2 mr-1"
|
||||||
aria-label="Elevation"
|
aria-label="Elevation"
|
||||||
/>
|
/>
|
||||||
<div>{node.position?.altitude} ft</div>
|
<div>
|
||||||
|
{formatQuantity(node.position?.altitude, {
|
||||||
|
one: "meter",
|
||||||
|
other: "meters",
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,7 +4,13 @@ import { Input } from "@components/UI/Input.tsx";
|
|||||||
import { useDevice } from "@core/stores/deviceStore.ts";
|
import { useDevice } from "@core/stores/deviceStore.ts";
|
||||||
import type { Types } from "@meshtastic/js";
|
import type { Types } from "@meshtastic/js";
|
||||||
import { SendIcon } from "lucide-react";
|
import { SendIcon } from "lucide-react";
|
||||||
import { type JSX, useCallback, useMemo, useState } from "react";
|
import {
|
||||||
|
type JSX,
|
||||||
|
startTransition,
|
||||||
|
useCallback,
|
||||||
|
useMemo,
|
||||||
|
useState,
|
||||||
|
} from "react";
|
||||||
|
|
||||||
export interface MessageInputProps {
|
export interface MessageInputProps {
|
||||||
to: Types.Destination;
|
to: Types.Destination;
|
||||||
@@ -76,26 +82,31 @@ export const MessageInput = ({
|
|||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<form
|
<form
|
||||||
className="w-full"
|
className="w-full"
|
||||||
onSubmit={(e) => {
|
action={async (formData: FormData) => {
|
||||||
e.preventDefault();
|
// prevent user from sending blank/empty message
|
||||||
sendText(localDraft);
|
if (localDraft === "") return;
|
||||||
|
const message = formData.get("messageInput") as string;
|
||||||
|
startTransition(() => {
|
||||||
|
sendText(message);
|
||||||
setLocalDraft("");
|
setLocalDraft("");
|
||||||
setMessageDraft("");
|
setMessageDraft("");
|
||||||
setMessageBytes(0);
|
setMessageBytes(0);
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex flex-grow gap-2">
|
<div className="flex flex-grow gap-2">
|
||||||
|
<span className="w-full">
|
||||||
<Input
|
<Input
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
minLength={1}
|
minLength={1}
|
||||||
|
name="messageInput"
|
||||||
placeholder="Enter Message"
|
placeholder="Enter Message"
|
||||||
value={localDraft}
|
value={localDraft}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
/>
|
/>
|
||||||
<div className="flex items-center w-24 p-2 place-content-end">
|
|
||||||
<span>
|
|
||||||
{messageBytes}/{maxBytes}
|
|
||||||
</span>
|
</span>
|
||||||
|
<div className="flex items-center w-24 p-2 place-content-end">
|
||||||
|
{messageBytes}/{maxBytes}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button type="submit">
|
<Button type="submit">
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const buttonVariants = cva(
|
|||||||
success:
|
success:
|
||||||
"bg-green-500 text-white hover:bg-green-600 dark:hover:bg-green-600",
|
"bg-green-500 text-white hover:bg-green-600 dark:hover:bg-green-600",
|
||||||
outline:
|
outline:
|
||||||
"bg-transparent border border-slate-200 hover:bg-slate-100 dark:border-slate-700 dark:text-slate-100",
|
"bg-transparent border border-slate-200 hover:bg-slate-100 dark:border-slate-400 dark:text-slate-100",
|
||||||
subtle:
|
subtle:
|
||||||
"bg-slate-100 text-slate-900 hover:bg-slate-200 dark:bg-slate-700 dark:text-slate-100",
|
"bg-slate-100 text-slate-900 hover:bg-slate-200 dark:bg-slate-700 dark:text-slate-100",
|
||||||
ghost:
|
ghost:
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const toastVariants = cva(
|
|||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default:
|
default:
|
||||||
"border bg-background text-foreground dark:bg-slate-700 dark:border-slate-600 dark:text-slate-50",
|
"border bg-backgroundPrimary text-foreground dark:bg-slate-700 dark:border-slate-600 dark:text-slate-50",
|
||||||
destructive:
|
destructive:
|
||||||
"group destructive bg-red-600 text-white dark:border-red-900 dark:bg-red-900 dark:text-red-50",
|
"group destructive bg-red-600 text-white dark:border-red-900 dark:bg-red-900 dark:text-red-50",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
interface PluralForms {
|
||||||
|
one: string;
|
||||||
|
other: string;
|
||||||
|
[key: string]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FormatOptions {
|
||||||
|
locale?: string;
|
||||||
|
pluralRules?: Intl.PluralRulesOptions;
|
||||||
|
numberFormat?: Intl.NumberFormatOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatQuantity(
|
||||||
|
value: number,
|
||||||
|
forms: PluralForms,
|
||||||
|
options: FormatOptions = {},
|
||||||
|
) {
|
||||||
|
const {
|
||||||
|
locale = "en-US",
|
||||||
|
pluralRules: pluralOptions = { type: "cardinal" },
|
||||||
|
numberFormat: numberOptions = {},
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
const pluralRules = new Intl.PluralRules(locale, pluralOptions);
|
||||||
|
const numberFormat = new Intl.NumberFormat(locale, numberOptions);
|
||||||
|
|
||||||
|
const pluralCategory = pluralRules.select(value);
|
||||||
|
const word = forms[pluralCategory];
|
||||||
|
|
||||||
|
return `${numberFormat.format(value)} ${word}`;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user