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

weather@mockturtl Add more tags, add padding options #6455

Draft
wants to merge 14 commits into
base: master
Choose a base branch
from

Conversation

aperkins81
Copy link
Contributor

No description provided.

@rcalixte rcalixte marked this pull request as draft September 30, 2024 09:44
@rcalixte
Copy link
Member

cc @Gr3q

Copy link
Contributor

@Gr3q Gr3q left a comment

Choose a reason for hiding this comment

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

Please increment the version in metadata.json and add the new version to CHANGELOG.md.

Edit: Looks nice, I will test it when I get home.

['t_h_diff', tempHourDiff],
['br', "\n"]
];
var regexp, match, pad, padLeft, padChar, newVal, isLiteral, padLiteral, dontPad;
Copy link
Contributor

Choose a reason for hiding this comment

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

Use let

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think that's all up to date, let me know if you spot anything else, cheers :)

const dayLength = ToHoursMinutes(weather.sunset - weather.sunrise);
const now = new Date();
const sunny = now > weather.sunrise && now < weather.sunset;
const daylightRemain = sunny ? ToHoursMinutes(weather.sunset - now) : "";
Copy link
Contributor

Choose a reason for hiding this comment

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

This might be incorrect if the system timezone doesn't match the locations timezone (maybe it's all ok, I'm just not sure).

Please verify by testing a location outside your timezone.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Tested in another time zone, seems to work despite Date not containing timezone info.

const tempsTomorrowWithDifferences = tmr ? tempsTomorrow + " (" + tmrMinTempChange + " / " + tmrMaxTempChange + ")" : "";
const sunset = (GetHoursMinutes(weather.sunset, config._show24Hours));
const sunrise = (GetHoursMinutes(weather.sunrise, config._show24Hours));
const dayLength = ToHoursMinutes(weather.sunset - weather.sunrise);
Copy link
Contributor

Choose a reason for hiding this comment

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

Intl.DurationFormat doesn't exist in cjs at all so I guess there is no other option and I don't want you to add another lib like humanizeDuration so this is fine.

@aperkins81
Copy link
Contributor Author

OK will stop adding stuff on this PR :) let me know if any changes are required, cheers

Copy link
Contributor

@Gr3q Gr3q left a comment

Choose a reason for hiding this comment

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

You have a bunch of type and eslint errors, including things that would break support with Cinnamon 3.8. You will have to edit this in something with typescript and eslint integration.

Easiest is with vscode but you can use something else, the main thing is that you will need to open the weather@mockturtl folder directly so it uses the tsconfig.json correctly.

Or you can validate from the terminal, these should not return any errors:

  • npx tsc -p ./src/3_8/tsconfig.json --noEmit
  • npm run lint

As for code changes I would suggest something like this (I don't know what true means in ['t', temp, 4, true], for example, so if you use an interface it's more readable):

type InjectItem =
	"t" |
	"u" |
	"c" |
	"c_long" |
	"dew_point" |
	"humidity" |
	"pressure" |
	"pressure_unit" |
	"extra_value" |
	"extra_name" |
	"city" |
	"country" |
	"search_entry" |
	"last_updated" |
	"wind_speed" |
	"wind_dir" |
	"wind_arrow" |
	"wind_deg" |
	"wind_unit" |
	"min" |
	"max" |
	"tmr_min" |
	"tmr_max" |
	"tmr_min_diff" |
	"tmr_max_diff" |
	"tmr_c" |
	"tmr_t" |
	"tmr_td" |
	"sunset" |
	"sunrise" |
	"day_length" |
	"day_remain" |
	"day_len_rem" |
	"day_rem_pct" |
	"t_h_diff" |
	"br";
;

interface PaddingDefault {
	padding?: number;
}

export const INJECT_ITEMS: Record<InjectItem, PaddingDefault> = {
	"t": { padding: 4 },
	"u": {},
	"c": {},
	"c_long": {},
	"dew_point": {},
	"humidity": { padding: 3 },
	"pressure": { padding: 7 },
	"pressure_unit": {},
	"extra_value": {},
	"extra_name": {},
	"city": {},
	"country": {},
	"search_entry": {},
	"last_updated": {},
	"wind_speed": {},
	"wind_dir": {},
	"wind_arrow": {},
	"wind_deg": {},
	"wind_unit": {},
	"min": {},
	"max": {},
	"tmr_min": {},
	"tmr_max": {},
	"tmr_min_diff": {},
	"tmr_max_diff": {},
	"tmr_c": {},
	"tmr_t": {},
	"tmr_td": {},
	"sunset": {},
	"sunrise": {},
	"day_length": {},
	"day_remain": {},
	"day_len_rem": {},
	"day_rem_pct": {},
	"t_h_diff": {},
	"br": {}
};

export function InjectValues(text: string, weather: WeatherData, config: Config, inCommand: boolean = false): string {
   ...
   const valuesPaddingDefaults: Record<InjectItem, string> = {
	    't': TempToUserConfig(weather.temperature, config, false) ?? "",
	    'u': UnitToUnicode(config.TemperatureUnit),
	    'c': weather.condition.main,
	    'c_long': weather.condition.description,
	    'dew_point': TempToUserConfig(weather.dewPoint, config, false) ?? "",
	    'humidity': weather.humidity?.toString() ?? "",
	    'pressure': weather.pressure != null ? PressToUserUnits(weather.pressure, config._pressureUnit).toString() : "",
	    'pressure_unit': config._pressureUnit,
	    'extra_value': weather.extra_field ? ExtraFieldToUserUnits(weather.extra_field, config) : "",
	    'extra_name': weather.extra_field ? weather.extra_field.name : "",
	    'city': weather.location.city ?? "",
	    'country': weather.location.country ?? "",
	    'search_entry': config.CurrentLocation?.entryText ?? "",
	    'last_updated': AwareDateString(weather.date, config._show24Hours, DateTime.local().zoneName),
	    'wind_speed': weather.wind.speed != null ? MPStoUserUnits(weather.wind.speed, windUnit) : "",
	    'wind_dir': weather.wind.degree != null ? CompassDirectionText(weather.wind.degree) : "",
	    'wind_arrow': weather.wind.degree != null ? CompassDirectionArrow(weather.wind.degree) : "",
	    'wind_deg': weather.wind.degree != null ? weather.wind.degree.toString() : "",
   ...

So it's strictly typed.

@aperkins81
Copy link
Contributor Author

aperkins81 commented Oct 2, 2024

I have removed all the warnings in vscode except for 1, it is complaining about using regex groups:

Property 'groups' does not exist on type 'RegExpExecArray'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2018' or later.ts(2550)

How do I change to es2018 or is that error misleading or ?

Edit: microsoft/TypeScript#32098

export function InjectValues(text: string, weather: WeatherData, config: Config, inCommand: boolean = false): string {
	const lastUpdatedTime = AwareDateString(weather.date, config._show24Hours, DateTime.local().zoneName);
	const temp = TempToUserConfig(weather.temperature, config, false) ?? "";
	const tempUnit = UnitToUnicode(config.TemperatureUnit);
	const condition = weather.condition.main;
	const conditionLong = weather.condition.description;
	const dewPoint = TempToUserConfig(weather.dewPoint, config, false) ?? "";
	const humidity = weather.humidity?.toString() ?? "";
	const pressure = weather.pressure != null ? PressToUserUnits(weather.pressure, config._pressureUnit).toString() : "";
	const pressureUnit = config._pressureUnit;
	const extraValue = weather.extra_field ? ExtraFieldToUserUnits(weather.extra_field, config) : "";
	const extraName = weather.extra_field ? weather.extra_field.name : "";
	const windUnit = config.WindSpeedUnit;
	const windSpeed = weather.wind.speed != null ? MPStoUserUnits(weather.wind.speed, windUnit) : "";
	const windDir = weather.wind.degree != null ? CompassDirectionText(weather.wind.degree) : "";
	const windArrow = weather.wind.degree != null ? CompassDirectionArrow(weather.wind.degree) : "";
	const windDegree = weather.wind.degree != null ? weather.wind.degree.toString() : "";
	const city = weather.location.city ?? "";
	const country = weather.location.country ?? "";
	const searchEntry = config.CurrentLocation?.entryText ?? "";
	const tmr = weather.forecasts && weather.forecasts[1] ? weather.forecasts[1] : null;
	const forecastHours = weather.hourlyForecasts && weather.hourlyForecasts[2] ? weather.hourlyForecasts : null;
	const forecastNow = forecastHours ? forecastHours[0] : null;
	const forecastHour = forecastHours ? forecastHours[2] ?? null : null;
	const tempHourDiff = forecastNow && forecastHour && forecastNow.temp && forecastHour.temp? ValueChange(forecastNow.temp, forecastHour.temp, 15) : "";
	const conditionTomorrow = tmr ? tmr.condition.main ?? "" : "";
	const tempMin = tmr ? TempToUserConfig(weather.forecasts[0].temp_min, config, false) ?? null : null;
	const tempMax = tmr ? TempToUserConfig(weather.forecasts[0].temp_max, config, false) ?? null : null;
	const tempMinTomorrow = tmr ? TempToUserConfig(tmr.temp_min, config, false) ?? null : null;
	const tempMaxTomorrow = tmr ? TempToUserConfig(tmr.temp_max, config, false) ?? null : null;
	const tempsTomorrow = tmr ? TempRangeToUserConfig(tmr.temp_min, tmr.temp_max, config) : null;
	const tmrMinTempChange = tempMinTomorrow && tempMax ? SignedNumber(Number(tempMaxTomorrow) - Number(tempMax)) ?? "" : "";
	const tmrMaxTempChange = tempMaxTomorrow && temp ? SignedNumber(Number(tempMaxTomorrow) - Number(tempMax)) ?? "" : "";
	const tempsTomorrowWithDifferences = tmr ? tempsTomorrow + " (" + tmrMinTempChange + " / " + tmrMaxTempChange + ")" : "";
	const sunset = (GetHoursMinutes(weather.sunset, config._show24Hours));
	const sunrise = (GetHoursMinutes(weather.sunrise, config._show24Hours));
	const dayLen = weather.sunset - weather.sunrise;
	const dayLength = ToHoursMinutes(dayLen);
	const dateNow = new Date();
	const sunny = dateNow > weather.sunrise && dateNow < weather.sunset;
	const dayRem = weather.sunset - dateNow.valueOf();
	const daylightRemain = sunny ? ToHoursMinutes(dayRem) : "";
	const daylightRemainPct = sunny ? Math.round(dayRem * 100 / dayLen).toString() : "0";
	const dayLengthLightRemain = dayLength + (sunny ? " (" + daylightRemain + ")" : "");
	const valuesPaddingDefaults = [
		['t', temp, 4, true],
		['u', tempUnit],
		['c', condition],
		['c_long', conditionLong],
		['dew_point', dewPoint],
		['humidity', humidity, 3],
		['pressure', pressure, 7],
		['pressure_unit', pressureUnit],
		['extra_value', extraValue],
		['extra_name', extraName],
		['city', city],
		['country', country],
		['search_entry', searchEntry],
		['last_updated', lastUpdatedTime],
		['wind_speed', windSpeed],
		['wind_dir', windDir],
		['wind_arrow', windArrow],
		['wind_deg', windDegree],
		['wind_unit', windUnit],
		['min', tempMin],
		['max', tempMax],
		['tmr_min', tempMinTomorrow],
		['tmr_max', tempMaxTomorrow],
		['tmr_min_diff', tmrMinTempChange],
		['tmr_max_diff', tmrMaxTempChange],
		['tmr_c', conditionTomorrow],
		['tmr_t', tempsTomorrow],
		['tmr_td', tempsTomorrowWithDifferences],
		['sunset', sunset],
		['sunrise', sunrise],
		['day_length', dayLength],
		['day_remain', daylightRemain],
		['day_len_rem', dayLengthLightRemain],
		['day_rem_pct', daylightRemainPct],
		['t_h_diff', tempHourDiff],
		['br', "\n"]
	];
	let regexp, match, groups, pad, padLeft, padChar, newVal, isLiteral, padLiteral, noPad;
	for (const value of valuesPaddingDefaults) {
		if (!value[0] || !value[1]) {
			continue;
		}
		regexp = new RegExp(
			'(?<isLiteral>\\{{1,3})' +
			'(?<value>\\b' + EscapeRegex(value[0].toString()) + '\\b)' +
			'(?<padLeft>[,\\.]{0,1})' +
			'(?<pad>\\d{0,2})' +
			'\\.{0,1}(?<padChar>[^\\}]{0,1})' +
			'(?<isLiteralEnd>\\}{1,3})', 'g');
		if (!regexp) {
			continue;
		}
		match = regexp.exec(text);
		if (!match) {
			continue;
		}
		groups = match.groups;
		padLiteral = groups!.isLiteral == "{{{" && groups.isLiteralEnd == "}}}";
		isLiteral = groups.isLiteral == "{{" && groups.isLiteralEnd == "}}";
		noPad = inCommand && !padLiteral;
		padLeft = groups.padLeft ? groups.padLeft == ',' : value[3] != false;
		pad = groups.pad ? groups.pad : value[2] || 0;
		padChar = groups.padChar ? groups.padChar : value[4] || ' ';
		newVal = value[1].toString();
		newVal = noPad ? newVal : padLeft ? newVal.padStart(pad, padChar) : newVal.padEnd(pad, padChar);
		text = text.replace(regexp, isLiteral || padLiteral ? Literal(newVal) : newVal);
	}
	return text;
}

@rcalixte
Copy link
Member

rcalixte commented Oct 2, 2024

including things that would break support with Cinnamon 3.8

If it helps, just a note that Cinnamon 3.8 shipped with Mint 19.0 which was in turn based on Ubuntu 18.04 which ended standard support in 2023. At this point, it would be safe to create a new target version directory going forward and leaving the 3.8 folder for everything in-between. The new version folder could be 5.4 or 6.2. All prior versions of Cinnamon would be served by the 3.8 folder (and hopefully only requiring minimal maintenance) while new features, functionality, and/or fixes can be focused on more recent versions.

@aperkins81
Copy link
Contributor Author

aperkins81 commented Oct 2, 2024

I think I will move the overrides to a new tab in the settings, and have a Tree section for padding defaults. https://github.com/linuxmint/cinnamon/blob/1e43299b9ad548c9395edfd456cbba017ca02b9f/files/usr/share/cinnamon/applets/settings-example%40cinnamon.org/settings-schema.json#L218
Edit: more on its own tab, I am implementing presets and plan to have conditional presets to allow compact panel when no weather events. For example, if {temperature change in the next 2 hours} is > x then show y preset (maybe a custom Python module for settings). And later on have more tags for changes in weather

@Gr3q
Copy link
Contributor

Gr3q commented Oct 3, 2024

If it helps, just a note that Cinnamon 3.8 shipped with Mint 19.0 which was in turn based on Ubuntu 18.04 which ended standard support in 2023. At this point, it would be safe to create a new target version directory going forward and leaving the 3.8 folder for everything in-between. The new version folder could be 5.4 or 6.2. All prior versions of Cinnamon would be served by the 3.8 folder (and hopefully only requiring minimal maintenance) while new features, functionality, and/or fixes can be focused on more recent versions.

There will be a day when something comes up to abandon older versions, this is really not it. @aperkins81 if you remove named capturing groups from the regex and use regular capturing groups, it will work.

Cinnamon is also available on Debian, so I will try to support 3.8 as long as it's not a huge burden (like it used to be with 3.2 and 3.6). I can use all new language features with a few exceptions, this is one of them.

@Gr3q
Copy link
Contributor

Gr3q commented Oct 3, 2024

I have removed all the warnings in vscode except for 1, it is complaining about using regex groups:

You should commit the code. And I can see you still don't handle the case if sunset or sunrise is null

I think I will move the overrides to a new tab in the settings, and have a Tree section for padding defaults. https://github.com/linuxmint/cinnamon/blob/1e43299b9ad548c9395edfd456cbba017ca02b9f/files/usr/share/cinnamon/applets/settings-example%40cinnamon.org/settings-schema.json#L218

The list setting element is the best out of all elements for what you are trying to do but it's still not the ideal, because the user can add/remove items from it and we have a fixed set items, you just want users to edit them.

So either you copy the setting element from the Cinnamon source code and remove those buttons or you add code on the applet side every time to populate them (which you will need to do anyway because the list of what we support can change - expand - from version to version)

Edit: more on its own tab, I am implementing presets and plan to have conditional presets to allow compact panel when no weather events. For example, if {temperature change in the next 2 hours} is > x then show y preset (maybe a custom Python module for settings). And later on have more tags for changes in weather

That should be it's own PR, it sound's like a big job. to do that you would need to support and evaluate actual programming logic in settings.

You should create a list of all conditions and outputs you want to see in there with a priority order based on what kind of forecast is available (minutely, hourly, daily)

PS: For now just omit the extra features from this PR and focus on fixing the errors

@Gr3q
Copy link
Contributor

Gr3q commented Oct 3, 2024

@aperkins81 Alternatively I can open a PR on your fork where I fix all errors so it gets included in this PR, whichever you prefer.

@rcalixte
Copy link
Member

rcalixte commented Oct 3, 2024

Cinnamon is also available on Debian, so I will try to support 3.8 as long as it's not a huge burden (like it used to be with 3.2 and 3.6). I can use all new language features with a few exceptions, this is one of them.

  • Debian 10 shipped with Cinnamon 3.8 and ended long-term support in June 2024.
  • Debian 11 shipped with Cinnamon 4.8.1
  • Debian 12 shipped with Cinnamon 5.6.
  • Debian 13 (currently Testing) has Cinnamon 6.0 but this could be 6.2 or 6.4 before the final release.

Whether it be 4.8 or 5.4 as a new folder, you can safely leave 3.8 as it is. Hopefully this helps!

1.Debian 11 has also transitioned support from the Debian security and release teams to the LTS team.

@aperkins81
Copy link
Contributor Author

aperkins81 commented Oct 3, 2024

Yeah will keep conditional presets for another PR and fix those other errors today.
For now I have presets in a combobox - I asked ChatGPT for the 10 most useful single and 10 most useful double line presets then pasted the table from the README and sorted by alpha 1 line and 2 line presets. I am not attached to any of them so feel free to remove some or change them (except for 2nd last which is a preset I use)

	"tempTextOverridePreset": {
		"type": "combobox",
		"default": "custom",
		"description": "Override label on panel",
		"options": {
			"Custom": "custom",
			"Current Temperature and Condition": "{t} {u}, {c}",
			"Current Temperature, Condition, and Feels Like": "{t} {u}, {c}, Feels like: {extra_value} {u}",
			"Daylight Summary": "Day length: {day_length}, Remaining: {day_len_rem} ({day_rem_pct}%)",
			"Full Current Weather Report": "{t} {u}, {c_long}. Humidity: {humidity}%, Wind: {wind_speed} {wind_unit} {wind_dir}, Pressure: {pressure} {pressure_unit}",
			"Location and Current Weather": "{city}, {country}: {t} {u}, {c}",
			"Max and Min Temperature for Today": "Min: {min} {u}, Max: {max} {u}",
			"Pressure and Humidity": "Pressure: {pressure} {pressure_unit}, Humidity: {humidity}%",
			"Sunrise and Sunset Times": "Sunrise: {sunrise}, Sunset: {sunet}",
			"Tomorrow's Temperature Forecast": "Tomorrow: {tmr_min} {u} - {tmr_max} {u}, {tmr_c}",
			"Wind Direction and Degree": "Wind: {wind_speed} {wind_unit}, Direction: {wind_dir} ({wind_deg}°)",
			"Wind Information with Arrow": "{wind_speed} {wind_unit} {wind_dir} ({wind_arrow})",
			"Current Temperature, Condition, and Feels Like": "{t} {u}, {c}{br}Feels like: {extra_value} {u}",
			"Daylight Summary": "Day length: {day_length}{br}Remaining: {day_len_rem} ({day_rem_pct}%)",
			"Feels Like with Wind Info": "Feels like: {extra_value} {u}{br}Wind: {wind_speed} {wind_unit}, {wind_dir}",
			"Full Current Weather Report": "{t} {u}, {c_long}{br}Humidity: {humidity}%, Wind: {wind_speed} {wind_unit} {wind_dir}",
			"Location with Weather and Wind": "{city}, {country}: {t} {u}, {c}{br}Wind: {wind_speed} {wind_unit} {wind_dir} ({wind_arrow})",
			"Max/Min Temperature with Wind Info": "Min: {min} {u}, Max: {max} {u}{br}Wind: {wind_speed} {wind_unit} {wind_dir}",
			"Pressure and Humidity with Wind": "Pressure: {pressure} {pressure_unit}, Humidity: {humidity}%{br}Wind: {wind_speed} {wind_unit}, {wind_dir}",
			"Sunrise and Sunset with Day Length": "Sunrise: {sunrise}, Sunset: {sunet}{br}Day length: {day_length}",
			"Tomorrow's Forecast with Conditions": "Tomorrow: {tmr_min} {u} - {tmr_max} {u}{br}{tmr_c}",
			"Compact detailed Weather Report": " {c} {t}{t_h_diff}{br} {wind_speed}{wind_arrow} {humidity}% {pressure} {day_remain}",
			"Wind Speed and Direction with Degree": "Wind: {wind_speed} {wind_unit}{br}Direction: {wind_dir} ({wind_deg}°)"
		},
		"tooltip": "Custom presets for label override"
	},
	"tempTextOverride": {
		"type": "entry",
		"default": "",
		"description": "Custom value:",
		"tooltip": "Some of the available values are: {c} is condition, {t} is temperature and {u} is unit.\nCan be used if label does not fit on vertical panel, among other smart things.",
		"dependency" : "tempTextOverridePreset=custom"
	},

and above:

		"panel-options": {
			"type": "section",
			"title": "Panel (Taskbar)",
			"keys": [
				"showTextInPanel",
				"showCommentInPanel",
				"tempTextOverride",
				"tempTextOverridePreset",
				"tooltipTextOverride"
			]
		},

Haven't tested that much as am dealing with another error but open to suggestions

(Edit: will put this in another PR)

@aperkins81
Copy link
Contributor Author

aperkins81 commented Oct 4, 2024

Note in last commit after running ./build.sh it made a heap of changes in the generated weather-applet.js - is this normal or do I have something misconfigured? (Edit: it also changed a heap of translation files, I discarded changes of this because I did not know what it was doing, but if you would like I can generate them and add them to the commit)

@aperkins81
Copy link
Contributor Author

aperkins81 commented Oct 4, 2024

As for code changes I would suggest something like this (I don't know what true means in ['t', temp, 4, true], for example, so if you use an interface it's more readable):

After 12 years of Ruby on Rails adhering to DRY principle, I physically cannot triplicate that list ;) I ran it through ChatGPT and it gave more descriptive variable names so hoping existing is all good

@aperkins81
Copy link
Contributor Author

Just a note for the next version supporting es2018 there is a linter requiring named groups for readability https://eslint.org/docs/latest/rules/prefer-named-capture-group

@Gr3q
Copy link
Contributor

Gr3q commented Oct 5, 2024

Note in last commit after running ./build.sh it made a heap of changes in the generated weather-applet.js - is this normal or do I have something misconfigured? (Edit: it also changed a heap of translation files, I discarded changes of this because I did not know what it was doing, but if you would like I can generate them and add them to the commit)

You should generate and commit translations, they were changed after all.

build.sh is a bit outdated, assuming you have nodejs and npm installed, you can run this to verify from weather@mockturtl folder:

npm ci
npm watch # this will not exit, it will watch for changes after building (if there are errors, it will not output) 

If you still have a lot of changes after that then it must be the nodejs/npm version difference and they can be committed.

@Gr3q
Copy link
Contributor

Gr3q commented Oct 5, 2024

After 12 years of Ruby on Rails adhering to DRY principle, I physically cannot triplicate that list ;) I ran it through ChatGPT and it gave more descriptive variable names so hoping existing is all good

I understand where you are coming from, in that case type InjectItem is the source of truth, with that you can enforce a Dictionary (Record) to must have all the keys from that type. It's not really duplication, but again you don't have to do it that way.

Just a note for the next version supporting es2018 there is a linter requiring named groups for readability https://eslint.org/docs/latest/rules/prefer-named-capture-group

I agree named capturing groups are much more readable and I prefer them too, and I will add it as a rule when I break compatibility with older versions.

It's most likely will be when anything below Cinnamon 5.4 stops being supported, or whatever version the Soup library version has changed in Cinnamon.

// Sunrise and sunset calculations
const sunsetTime = sunset ? GetHoursMinutes(sunset, _show24Hours) : "";
const sunriseTime = sunrise ? GetHoursMinutes(sunrise, _show24Hours) : "";
const dayLength = sunset && sunrise ? ToHoursMinutes(Number(sunset) - Number(sunrise)) : "";
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this safe? GetHoursMinutes can output wildly different strings based on the user's locale. Have you tried it with german, hungarian or korean locale?

It's easiest to test if you add a line date.setLocale("yourlocale"); inside GetHoursMinutes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will get in a patch today to use the builtins, been sidetracked with housework; was initially largely unaware of the TypeScript as I developed in in JS, but another skill to learn is good, will try help out with other issues and would next like to build a text VU meter that by default uses coloured |||||| (and some nice utf8 symbols as themes) but also can use the output from a file (eg, this weather applet, then set panel text to off in this applet). PS love Cinnamon, it was the only sane option when Gnome 3 was forced on us, and back in the day I wrote a battery applet for Gnome 2. These days I have been using CachyOS for the last few months and before that Arch for a good 15 years after Ubuntu. Also I have a WIP that the robot (mostly) made, I have been using Looking Glass to debug.

#!/bin/bash
# REQUIREMENTS:
# - typescript installed
version='3.8'
TAIL_OUTPUT=false  # Set to true if you want to keep the script running (tail output)

# Run the npm lint command and capture its output
lint_output=$(npm run lint 2>&1)

# Use awk and sed to extract and clean the number of errors and warnings
errors=$(echo "$lint_output" | awk '/problems/ {print $4}' | sed 's/[()]//g')
warnings=$(echo "$lint_output" | awk '/problems/ {print $6}' | sed 's/[()]//g')

echo "Errors: $errors"
echo "Warnings: $warnings"

# Check if there are zero errors
if [ "$errors" -eq 0 ]; then
  SOURCE="${BASH_SOURCE[0]}"
  while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
    DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null && pwd )"
    SOURCE="$(readlink "$SOURCE")"
    [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
  done
  DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null && pwd )"

  # Save current dir for convenience
  path=${PWD}

  # Run the npx webpack command and capture its output
  webpack_output=$(npx webpack 2>&1)
  echo "$webpack_output"

  # Check if the word 'successfully' is in the output
  if echo "$webpack_output" | grep -q "compiled successfully in"; then
      cp --verbose files/weather@mockturtl/${version}/weather-applet.js ~/.local/share/cinnamon/applets/weather\@mockturtl/3.8/weather-applet.js
      
      # Restart Cinnamon in the background without terminating the script
      nohup bash -c "export DISPLAY=:0; cinnamon --replace" > /dev/null 2>&1 &
      
      if [ "$TAIL_OUTPUT" = true ]; then
          # Tail the output to keep the script running
          tail -f /dev/null  # Keep the script running indefinitely
      else
          echo "Build and installation successful, exiting."
          exit 0  # Exit the script
      fi
  else
      echo "Errors prevented compiling"
      exit -2
  fi
else
   echo "Errors prevented compiling: $lint_output"
   exit -1
fi

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants