This commit is contained in:
thororen1234 2024-07-31 15:52:34 -04:00
parent 38bba2d900
commit b93c0aa1d4
17 changed files with 1233 additions and 28 deletions

View file

@ -0,0 +1,66 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2023 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { classNameFactory } from "@api/Styles";
import { useState } from "@webpack/common";
import { Message } from "discord-types/general";
export const conversions = new Map<string, (conv: string) => void>();
const cl = classNameFactory("vc-converter-");
function Dismiss({ onDismiss }: { onDismiss: () => void; }) {
return (
<button
onClick={onDismiss}
className={cl("dismiss")}
>
Dismiss
</button>
);
}
// thanks <@408047304864432139>
export function ConvertIcon({ height = 24, width = 24, className }: {
height?: number,
width?: number,
className?: string;
}) {
return (
<svg
viewBox="0 0 98 98"
height={height}
width={width}
className={[cl("icon"), className].join(" ")}
>
<path
fill="currentColor"
d="m50 16.668v-7.4609c0-1.875-2.25-2.7891-3.543-1.457l-11.664 11.625c-0.83594 0.83203-0.83594 2.125 0 2.957l11.625 11.625c1.332 1.293 3.582 0.375 3.582-1.5v-7.457c13.793 0 25 11.207 25 25 0 3.293-0.625 6.5-1.832 9.375-0.625 1.5-0.16797 3.207 0.95703 4.332 2.125 2.125 5.707 1.375 6.832-1.4141 1.543-3.793 2.375-7.9609 2.375-12.293 0-18.418-14.914-33.332-33.332-33.332zm0 58.332c-13.793 0-25-11.207-25-25 0-3.293 0.625-6.5 1.832-9.375 0.625-1.5 0.16797-3.207-0.95703-4.332-2.125-2.125-5.707-1.375-6.832 1.4141-1.543 3.793-2.375 7.9609-2.375 12.293 0 18.418 14.914 33.332 33.332 33.332v7.4609c0 1.875 2.25 2.7891 3.543 1.457l11.625-11.625c0.83203-0.83203 0.83203-2.125 0-2.957l-11.625-11.625c-1.293-1.293-3.543-0.375-3.543 1.5z" />
</svg>
);
}
export function ConverterAccessory({ message }: { message: Message; }) {
const [conversion, setConversion] = useState<string>("");
conversions.set(message.id, setConversion);
if (!conversion) return null;
return (
<span className={cl("accessory")}>
<ConvertIcon width={16} height={16} />
{conversion}
{" - "}
<Dismiss onDismiss={() => setConversion("")} />
</span>
);
}

View file

@ -0,0 +1,177 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { settings } from ".";
interface regexes {
imperial: {
[key: string]: {
regex: RegExp,
convert: (...groups: string[]) => string;
};
};
metric: {
[key: string]: {
regex: RegExp,
convert: (...groups: string[]) => string;
};
};
}
// TODO: add grams, kilograms, ounces, and pounds
const regexes: regexes = {
// matches imperial units, converts them to metric
imperial: {
farenheight: {
regex: /(-?\d+(?:\.\d+)?)°?(f)(?!\w)/ig,
convert(...groups) {
const c = ((parseFloat(groups[1]) - 32) * (5 / 9)).toFixed(2);
return `${c}°C`;
},
},
// feetMark: {
// regex: /(\d+(?:\.\d+))(')(?!(\d+(?:\.\d+)?(''|")|'))/g,
// convert(...groups) {
// },
// },
// leaving this one in because it is commonly used for something like 5'9'' for a persons height
feetInchesMark: {
regex: /(\d+)(') ?(\d+(?:\.\d+)?)("|'')?/g,
convert(...groups) {
let ftin = parseFloat(groups[1]) / 3.281;
ftin += parseFloat(groups[3]) / 39.37;
return `${ftin.toFixed(2)}m`;
},
},
// inchesMark: {
// regex: /(?<!\d+')(\d+(?:\.\d+)?)("|'')/g,
// convert(...groups) {
// },
// },
feetWord: {
regex: /(\d+(?:\.\d+)?) *(f(ee)?t)(?! *\d)/ig,
convert(...groups) {
const ft = (parseFloat(groups[1]) / 3.281).toFixed(2);
return `${ft}m`;
},
},
inchesWord: {
regex: /(?<!\d+ *(?:f(?:ee|oo)?t) *)(\d+(?:\.\d+)?) *(in(?:ches?)?)/ig,
convert(...groups) {
const inches = (parseFloat(groups[1]) / 2.54).toFixed(2);
return `${inches}cm`;
},
},
feetInchesWord: {
regex: /(\d+) *(f(?:ee|oo)?t) *(\d+(?:\.\d+)?) *(in(?:ches?)?)/ig,
convert(...groups) {
let ftin = parseFloat(groups[1]) / 3.281;
ftin += parseFloat(groups[3]) / 39.37;
return `${ftin.toFixed(2)}m`;
},
},
poundWord: {
regex: /(\d+(?:\.\d+)?) *(lbs?|pounds?)(?! ?\d)/ig,
convert(...groups: string[]) {
const lbs = (parseFloat(groups[1]) / 2.205).toFixed(2);
return `${lbs}kg`;
},
},
poundOunceWord: {
regex: /(\d+(?:\.\d+)?) *(lbs?|pounds?) *(\d+(?:\.\d+)?) *(ozs?|ounces?)/ig,
convert(...groups) {
let lbs = (parseInt(groups[1]) / 2.205);
lbs += (parseFloat(groups[2]) / 35.274);
return `${lbs.toFixed(2)}kg`;
}
},
ounceWord: {
regex: /(\d+(?:\.\d+)?) ?(ounces?|oz)/gi,
convert(...groups) {
const ozs = (parseFloat(groups[1]) * 28.35).toFixed(2);
return `${ozs}g`;
},
},
milesPerHour: {
regex: /(\d+(?:\.\d+)?) ?(m(?:p|\/)h)/gi,
convert(...groups) {
const mph = (parseFloat(groups[1]) * 1.609).toFixed(2);
return `${mph}km/h`;
},
}
},
// matches metric untis, converts them into imperial
metric: {
// i dont think people ever write metric units as 1m3cm or something like that
celcius: {
regex: /(-?\d+(?:\.\d+)?) ?°?(c)(?!\w)/ig,
convert(...groups) {
const f = ((parseFloat(groups[1]) * (9 / 5)) + 32).toFixed(2);
return `${f}°F`;
}
},
// convert to inches
centimeters: {
regex: /(\d+(?:\.\d+)?) *(cm)(?!\w)/ig,
convert(...groups) {
const cm = (parseFloat(groups[1]) / 2.54).toFixed(2);
return `${cm}in`;
},
},
// convert to feet
meters: {
regex: /(\d+(?:\.\d+)?) *(m)(?!\w)/ig,
convert(...groups) {
const m = parseFloat((parseFloat(groups[1]) * 3.821).toFixed(2));
if (Number.isInteger(m))
return `${m}ft`;
return `${m.toFixed(0)}ft${((m % 1) * 12).toFixed(2)}in`;
},
},
// covnert to miles
kilometers: {
regex: /(\d+(?:\.\d+)?) *(km)(?!\w)/ig,
convert(...groups) {
const m = (parseFloat(groups[1]) / 1.609).toFixed(2);
return `${m}mi`;
},
},
grams: {
regex: /(\d+(?:\.\d+)?) ?(grams?|g)/gi,
convert(...groups) {
const g = (parseFloat(groups[1]) / 28.35).toFixed(2);
return `${g}oz(s)`;
},
},
kilograms: {
regex: /(\d+(?:\.\d+)?) ?(kg|kilos?)/gi,
convert(...groups) {
const kg = (parseFloat(groups[1]) * 2.205).toFixed(2);
return `${kg}lb(s)`;
},
},
kilometersPerHour: {
regex: /(\d+(?:\.\d+)?) ?(km?p?\/?h)/gi,
convert(...groups) {
const kph = (parseFloat(groups[1]) / 1.609).toFixed(2);
return `${kph}mph`;
},
}
}
};
export function convert(message: string): string {
let newMessage = message;
if (settings.store.myUnits === "imperial") {
for (const unit in regexes.metric) {
newMessage = newMessage.replaceAll(regexes.metric[unit].regex, regexes.metric[unit].convert);
}
} else {
for (const unit in regexes.imperial) {
newMessage = newMessage.replaceAll(regexes.imperial[unit].regex, regexes.imperial[unit].convert);
}
}
return newMessage;
}

View file

@ -0,0 +1,77 @@
/*
* Vencord, a modification for Discord's desktop app
* Copyright (c) 2022 Vendicated and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import "./style.css";
import { addAccessory } from "@api/MessageAccessories";
import { addButton } from "@api/MessagePopover";
import { definePluginSettings } from "@api/Settings";
import { EquicordDevs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
import { ChannelStore } from "@webpack/common";
import { convert } from "./converter";
import { conversions, ConverterAccessory, ConvertIcon } from "./ConverterAccessory";
export const settings = definePluginSettings({
myUnits: {
type: OptionType.SELECT,
description: "the units you use and want things converted to. defaults to imperial",
options: [
{
default: true,
label: "Imperial",
value: "imperial",
},
{
label: "Metric",
value: "metric"
}
]
},
// invert: {
// type: OptionType.BOOLEAN,
// default: false,
// // is there a better way to word this?
// description: "If this option is set, ignore the units you set and invert every conversion."
// }
});
export default definePlugin({
name: "UnitConverter",
description: "Converts metric units to Imperal units and vice versa",
authors: [EquicordDevs.sadan],
start() {
addAccessory("vc-converter", props => <ConverterAccessory message={props.message} />);
addButton("vc-converter", message => {
if (!message.content) return null;
return {
label: "Convert Units",
icon: ConvertIcon,
message,
channel: ChannelStore.getChannel(message.channel_id),
onClick: async () => {
const setConversion = conversions.get(message.id);
if (!setConversion) return;
setConversion(convert(message.content));
}
};
});
},
settings,
});

View file

@ -0,0 +1,24 @@
.vc-converter-dismiss {
all: unset;
cursor: pointer;
color: var(--text-link);
}
.vc-converter-dismiss:is(:hover, :focus) {
text-decoration: underline;
}
.vc-converter-accessory {
color: var(--text-muted);
margin-top: 0.5em;
font-style: italic;
font-weight: 400;
}
.vc-converter-accessory svg {
margin-right: 0.25em;
}
.vc-converter-chat-button {
scale: 1.085;
}