M app/javascript/flavours/glitch/blurhash.ts => app/javascript/flavours/glitch/blurhash.ts +2 -3
@@ 86,10 86,9 @@ const DIGIT_CHARACTERS = [
export const decode83 = (str: string) => {
let value = 0;
- let c, digit;
+ let digit;
- for (let i = 0; i < str.length; i++) {
- c = str[i];
+ for (const c of str) {
digit = DIGIT_CHARACTERS.indexOf(c);
value = value * 83 + digit;
}
M app/javascript/flavours/glitch/components/autosuggest_hashtag.tsx => app/javascript/flavours/glitch/components/autosuggest_hashtag.tsx +2 -2
@@ 6,11 6,11 @@ interface Props {
tag: {
name: string;
url?: string;
- history?: Array<{
+ history?: {
uses: number;
accounts: string;
day: string;
- }>;
+ }[];
following?: boolean;
type: 'hashtag';
};
M app/javascript/flavours/glitch/components/display_name.tsx => app/javascript/flavours/glitch/components/display_name.tsx +1 -1
@@ 82,7 82,7 @@ export class DisplayName extends React.PureComponent<Props> {
} else if (account) {
let acct = account.get('acct');
- if (acct.indexOf('@') === -1 && localDomain) {
+ if (!acct.includes('@') && localDomain) {
acct = `${acct}@${localDomain}`;
}
M app/javascript/flavours/glitch/components/short_number.tsx => app/javascript/flavours/glitch/components/short_number.tsx +2 -2
@@ 29,12 29,12 @@ export const ShortNumberRenderer: React.FC<ShortNumberProps> = ({
);
}
- const customRenderer = children || renderer || null;
+ const customRenderer = children ?? renderer ?? null;
const displayNumber = <ShortNumberCounter value={shortNumber} />;
return (
- customRenderer?.(displayNumber, pluralReady(value, division)) ||
+ customRenderer?.(displayNumber, pluralReady(value, division)) ??
displayNumber
);
};
M app/javascript/flavours/glitch/features/emoji/emoji_compressed.d.ts => app/javascript/flavours/glitch/features/emoji/emoji_compressed.d.ts +4 -3
@@ 28,9 28,10 @@ export type SearchData = [
Emoji['unified'],
];
-export interface ShortCodesToEmojiData {
- [key: ShortCodesToEmojiDataKey]: [FilenameData, SearchData];
-}
+export type ShortCodesToEmojiData = Record<
+ ShortCodesToEmojiDataKey,
+ [FilenameData, SearchData]
+>;
export type EmojisWithoutShortCodes = FilenameData[];
export type EmojiCompressed = [
M app/javascript/flavours/glitch/features/emoji/emoji_mart_data_light.ts => app/javascript/flavours/glitch/features/emoji/emoji_mart_data_light.ts +1 -1
@@ 9,7 9,7 @@ import emojiCompressed from './emoji_compressed';
import { unicodeToUnifiedName } from './unicode_to_unified_name';
type Emojis = {
- [key in keyof ShortCodesToEmojiData]: {
+ [key in NonNullable<keyof ShortCodesToEmojiData>]: {
native: BaseEmoji['native'];
search: Search;
short_names: Emoji['short_names'];
M app/javascript/flavours/glitch/features/home_timeline/components/column_settings.tsx => app/javascript/flavours/glitch/features/home_timeline/components/column_settings.tsx +1 -1
@@ 19,7 19,7 @@ export const ColumnSettings: React.FC = () => {
const dispatch = useAppDispatch();
const onChange = useCallback(
(key: string, checked: boolean) => {
- void dispatch(changeSetting(['home', ...key], checked));
+ dispatch(changeSetting(['home', ...key], checked));
},
[dispatch],
);
M app/javascript/flavours/glitch/locales/global_locale.ts => app/javascript/flavours/glitch/locales/global_locale.ts +8 -4
@@ 3,15 3,19 @@ export interface LocaleData {
messages: Record<string, string>;
}
-let loadedLocale: LocaleData;
+let loadedLocale: LocaleData | undefined;
export function setLocale(locale: LocaleData) {
loadedLocale = locale;
}
-export function getLocale() {
- if (!loadedLocale && process.env.NODE_ENV === 'development') {
- throw new Error('getLocale() called before any locale has been set');
+export function getLocale(): LocaleData {
+ if (!loadedLocale) {
+ if (process.env.NODE_ENV === 'development') {
+ throw new Error('getLocale() called before any locale has been set');
+ } else {
+ return { locale: 'unknown', messages: {} };
+ }
}
return loadedLocale;
M app/javascript/flavours/glitch/locales/load_locale.ts => app/javascript/flavours/glitch/locales/load_locale.ts +1 -0
@@ 6,6 6,7 @@ import { isLocaleLoaded, setLocale } from './global_locale';
const localeLoadingSemaphore = new Semaphore(1);
export async function loadLocale() {
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- we want to match empty strings
const locale = document.querySelector<HTMLElement>('html')?.lang || 'en';
// We use a Semaphore here so only one thing can try to load the locales at
M app/javascript/flavours/glitch/polyfills/base_polyfills.ts => app/javascript/flavours/glitch/polyfills/base_polyfills.ts +2 -2
@@ 4,7 4,7 @@ import 'core-js/features/symbol';
import 'core-js/features/promise/finally';
import { decode as decodeBase64 } from '../utils/base64';
-if (!HTMLCanvasElement.prototype.toBlob) {
+if (!Object.hasOwn(HTMLCanvasElement.prototype, 'toBlob')) {
const BASE64_MARKER = ';base64,';
Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
@@ 17,7 17,7 @@ if (!HTMLCanvasElement.prototype.toBlob) {
const dataURL: string = this.toDataURL(type, quality);
let data;
- if (dataURL.indexOf(BASE64_MARKER) >= 0) {
+ if (dataURL.includes(BASE64_MARKER)) {
const [, base64] = dataURL.split(BASE64_MARKER);
data = decodeBase64(base64);
} else {
M app/javascript/flavours/glitch/polyfills/index.ts => app/javascript/flavours/glitch/polyfills/index.ts +2 -0
@@ 24,6 24,7 @@ export function loadPolyfills() {
// Latest version of Firefox and Safari do not have IntersectionObserver.
// Edge does not have requestIdleCallback.
// This avoids shipping them all the polyfills.
+ /* eslint-disable @typescript-eslint/no-unnecessary-condition -- those properties might not exist in old browsers, even if they are always here in types */
const needsExtraPolyfills = !(
window.AbortController &&
window.IntersectionObserver &&
@@ 31,6 32,7 @@ export function loadPolyfills() {
'isIntersecting' in IntersectionObserverEntry.prototype &&
window.requestIdleCallback
);
+ /* eslint-enable @typescript-eslint/no-unnecessary-condition */
return Promise.all([
loadIntlPolyfills(),
M app/javascript/flavours/glitch/polyfills/intl.ts => app/javascript/flavours/glitch/polyfills/intl.ts +1 -0
@@ 80,6 80,7 @@ async function loadIntlPluralRulesPolyfills(locale: string) {
// }
export async function loadIntlPolyfills() {
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- we want to match empty strings
const locale = document.querySelector('html')?.lang || 'en';
// order is important here
M app/javascript/flavours/glitch/scroll.ts => app/javascript/flavours/glitch/scroll.ts +10 -8
@@ 38,11 38,13 @@ const scroll = (
const isScrollBehaviorSupported =
'scrollBehavior' in document.documentElement.style;
-export const scrollRight = (node: Element, position: number) =>
- isScrollBehaviorSupported
- ? node.scrollTo({ left: position, behavior: 'smooth' })
- : scroll(node, 'scrollLeft', position);
-export const scrollTop = (node: Element) =>
- isScrollBehaviorSupported
- ? node.scrollTo({ top: 0, behavior: 'smooth' })
- : scroll(node, 'scrollTop', 0);
+export const scrollRight = (node: Element, position: number) => {
+ if (isScrollBehaviorSupported)
+ node.scrollTo({ left: position, behavior: 'smooth' });
+ else scroll(node, 'scrollLeft', position);
+};
+
+export const scrollTop = (node: Element) => {
+ if (isScrollBehaviorSupported) node.scrollTo({ top: 0, behavior: 'smooth' });
+ else scroll(node, 'scrollTop', 0);
+};
M app/javascript/flavours/glitch/store/middlewares/loading_bar.ts => app/javascript/flavours/glitch/store/middlewares/loading_bar.ts +2 -2
@@ 16,7 16,7 @@ const defaultTypeSuffixes: Config['promiseTypeSuffixes'] = [
export const loadingBarMiddleware = (
config: Config = {},
): Middleware<Record<string, never>, RootState> => {
- const promiseTypeSuffixes = config.promiseTypeSuffixes || defaultTypeSuffixes;
+ const promiseTypeSuffixes = config.promiseTypeSuffixes ?? defaultTypeSuffixes;
return ({ dispatch }) =>
(next) =>
@@ 32,7 32,7 @@ export const loadingBarMiddleware = (
if (action.type.match(isPending)) {
dispatch(showLoading());
} else if (
- action.type.match(isFulfilled) ||
+ action.type.match(isFulfilled) ??
action.type.match(isRejected)
) {
dispatch(hideLoading());
M app/javascript/flavours/glitch/store/middlewares/sounds.ts => app/javascript/flavours/glitch/store/middlewares/sounds.ts +3 -3
@@ 38,7 38,7 @@ export const soundsMiddleware = (): Middleware<
Record<string, never>,
RootState
> => {
- const soundCache: { [key: string]: HTMLAudioElement } = {};
+ const soundCache: Record<string, HTMLAudioElement> = {};
void ready(() => {
soundCache.boop = createAudio([
@@ 56,9 56,9 @@ export const soundsMiddleware = (): Middleware<
return () =>
(next) =>
(action: AnyAction & { meta?: { sound?: string } }) => {
- const sound = action?.meta?.sound;
+ const sound = action.meta?.sound;
- if (sound && soundCache[sound]) {
+ if (sound && Object.hasOwn(soundCache, sound)) {
play(soundCache[sound]);
}
M app/javascript/flavours/glitch/utils/filters.ts => app/javascript/flavours/glitch/utils/filters.ts +1 -1
@@ 7,7 7,7 @@ export const toServerSideType = (columnType: string) => {
case 'account':
return columnType;
default:
- if (columnType.indexOf('list:') > -1) {
+ if (columnType.includes('list:')) {
return 'home';
} else {
return 'public'; // community, account, hashtag
M app/javascript/flavours/glitch/utils/numbers.ts => app/javascript/flavours/glitch/utils/numbers.ts +1 -1
@@ 55,7 55,7 @@ export function toShortNumber(sourceNumber: number): ShortNumber {
*/
export function pluralReady(
sourceNumber: number,
- division: DecimalUnits,
+ division: DecimalUnits | null,
): number {
if (division == null || division < DECIMAL_UNITS.HUNDRED) {
return sourceNumber;
M app/javascript/flavours/glitch/uuid.ts => app/javascript/flavours/glitch/uuid.ts +1 -2
@@ 4,6 4,5 @@ export function uuid(a?: string): string {
(a as unknown as number) ^
((Math.random() * 16) >> ((a as unknown as number) / 4))
).toString(16)
- : // eslint-disable-next-line @typescript-eslint/restrict-plus-operands
- ('' + 1e7 + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, uuid);
+ : ('' + 1e7 + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, uuid);
}