From e38b39194075bec88af2f3a5134137563024d391 Mon Sep 17 00:00:00 2001
From: fusagiko / takayamaki <24884114+takayamaki@users.noreply.github.com>
Date: Wed, 3 May 2023 18:43:29 +0900
Subject: [PATCH] Add type annotation for some js files (#24787)

---
 .../mastodon/{blurhash.js => blurhash.ts}     |  6 ++--
 .../mastodon/{compare_id.js => compare_id.ts} |  2 +-
 .../mastodon/{is_mobile.js => is_mobile.ts}   | 20 ++++--------
 .../{permissions.js => permissions.ts}        |  0
 .../mastodon/{scroll.js => scroll.ts}         |  9 +++---
 .../mastodon/utils/{base64.js => base64.ts}   |  2 +-
 .../mastodon/utils/{filters.js => filters.ts} |  2 +-
 .../utils/{hashtags.js => hashtags.ts}        |  0
 .../mastodon/utils/{numbers.js => numbers.ts} | 31 +++++++------------
 app/javascript/types/resources.ts             |  6 +---
 app/javascript/types/util.ts                  |  7 +++++
 11 files changed, 36 insertions(+), 49 deletions(-)
 rename app/javascript/mastodon/{blurhash.js => blurhash.ts} (87%)
 rename app/javascript/mastodon/{compare_id.js => compare_id.ts} (72%)
 rename app/javascript/mastodon/{is_mobile.js => is_mobile.ts} (62%)
 rename app/javascript/mastodon/{permissions.js => permissions.ts} (100%)
 rename app/javascript/mastodon/{scroll.js => scroll.ts} (51%)
 rename app/javascript/mastodon/utils/{base64.js => base64.ts} (79%)
 rename app/javascript/mastodon/utils/{filters.js => filters.ts} (83%)
 rename app/javascript/mastodon/utils/{hashtags.js => hashtags.ts} (100%)
 rename app/javascript/mastodon/utils/{numbers.js => numbers.ts} (71%)
 create mode 100644 app/javascript/types/util.ts

diff --git a/app/javascript/mastodon/blurhash.js b/app/javascript/mastodon/blurhash.ts
similarity index 87%
rename from app/javascript/mastodon/blurhash.js
rename to app/javascript/mastodon/blurhash.ts
index 5adcc3e770..cb1c3b2c82 100644
--- a/app/javascript/mastodon/blurhash.js
+++ b/app/javascript/mastodon/blurhash.ts
@@ -84,7 +84,7 @@ const DIGIT_CHARACTERS = [
   '~',
 ];
 
-export const decode83 = (str) => {
+export const decode83 = (str: string) => {
   let value = 0;
   let c, digit;
 
@@ -97,13 +97,13 @@ export const decode83 = (str) => {
   return value;
 };
 
-export const intToRGB = int => ({
+export const intToRGB = (int: number) => ({
   r: Math.max(0, (int >> 16)),
   g: Math.max(0, (int >> 8) & 255),
   b: Math.max(0, (int & 255)),
 });
 
-export const getAverageFromBlurhash = blurhash => {
+export const getAverageFromBlurhash = (blurhash: string) => {
   if (!blurhash) {
     return null;
   }
diff --git a/app/javascript/mastodon/compare_id.js b/app/javascript/mastodon/compare_id.ts
similarity index 72%
rename from app/javascript/mastodon/compare_id.js
rename to app/javascript/mastodon/compare_id.ts
index d2bd74f447..ae4ac6f897 100644
--- a/app/javascript/mastodon/compare_id.js
+++ b/app/javascript/mastodon/compare_id.ts
@@ -1,4 +1,4 @@
-export default function compareId (id1, id2) {
+export default function compareId (id1: string, id2: string) {
   if (id1 === id2) {
     return 0;
   }
diff --git a/app/javascript/mastodon/is_mobile.js b/app/javascript/mastodon/is_mobile.ts
similarity index 62%
rename from app/javascript/mastodon/is_mobile.js
rename to app/javascript/mastodon/is_mobile.ts
index d0669b74bf..43819f85db 100644
--- a/app/javascript/mastodon/is_mobile.js
+++ b/app/javascript/mastodon/is_mobile.ts
@@ -1,21 +1,12 @@
-// @ts-check
-
 import { supportsPassiveEvents } from 'detect-passive-events';
-// @ts-expect-error
-import { forceSingleColumn } from 'mastodon/initial_state';
+import { forceSingleColumn } from './initial_state';
 
 const LAYOUT_BREAKPOINT = 630;
 
-/**
- * @param {number} width
- * @returns {boolean}
- */
-export const isMobile = width => width <= LAYOUT_BREAKPOINT;
+export const isMobile = (width: number) => width <= LAYOUT_BREAKPOINT;
 
-/**
- * @returns {string}
- */
-export const layoutFromWindow = () => {
+export type LayoutType = 'mobile' | 'single-column' | 'multi-column';
+export const layoutFromWindow = (): LayoutType => {
   if (isMobile(window.innerWidth)) {
     return 'mobile';
   } else if (forceSingleColumn) {
@@ -25,8 +16,9 @@ export const layoutFromWindow = () => {
   }
 };
 
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
 // @ts-expect-error
-const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
+const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && window.MSStream != null;
 
 const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
 
diff --git a/app/javascript/mastodon/permissions.js b/app/javascript/mastodon/permissions.ts
similarity index 100%
rename from app/javascript/mastodon/permissions.js
rename to app/javascript/mastodon/permissions.ts
diff --git a/app/javascript/mastodon/scroll.js b/app/javascript/mastodon/scroll.ts
similarity index 51%
rename from app/javascript/mastodon/scroll.js
rename to app/javascript/mastodon/scroll.ts
index 84fe582699..1e509c4175 100644
--- a/app/javascript/mastodon/scroll.js
+++ b/app/javascript/mastodon/scroll.ts
@@ -1,6 +1,5 @@
-const easingOutQuint = (x, t, b, c, d) => c * ((t = t / d - 1) * t * t * t * t + 1) + b;
-
-const scroll = (node, key, target) => {
+const easingOutQuint = (x: number, t: number, b: number, c: number, d: number) => c * ((t = t / d - 1) * t * t * t * t + 1) + b;
+const scroll = (node: Element, key: 'scrollTop' | 'scrollLeft', target: number) => {
   const startTime = Date.now();
   const offset    = node[key];
   const gap       = target - offset;
@@ -28,5 +27,5 @@ const scroll = (node, key, target) => {
 
 const isScrollBehaviorSupported = 'scrollBehavior' in document.documentElement.style;
 
-export const scrollRight = (node, position) => isScrollBehaviorSupported ? node.scrollTo({ left: position, behavior: 'smooth' }) : scroll(node, 'scrollLeft', position);
-export const scrollTop = (node) => isScrollBehaviorSupported ? node.scrollTo({ top: 0, behavior: 'smooth' }) : scroll(node, 'scrollTop', 0);
+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);
diff --git a/app/javascript/mastodon/utils/base64.js b/app/javascript/mastodon/utils/base64.ts
similarity index 79%
rename from app/javascript/mastodon/utils/base64.js
rename to app/javascript/mastodon/utils/base64.ts
index 8226e2c54e..5a595ee12b 100644
--- a/app/javascript/mastodon/utils/base64.js
+++ b/app/javascript/mastodon/utils/base64.ts
@@ -1,4 +1,4 @@
-export const decode = base64 => {
+export const decode = (base64: string): Uint8Array => {
   const rawData = window.atob(base64);
   const outputArray = new Uint8Array(rawData.length);
 
diff --git a/app/javascript/mastodon/utils/filters.js b/app/javascript/mastodon/utils/filters.ts
similarity index 83%
rename from app/javascript/mastodon/utils/filters.js
rename to app/javascript/mastodon/utils/filters.ts
index 97b433a991..5af2aa96a4 100644
--- a/app/javascript/mastodon/utils/filters.js
+++ b/app/javascript/mastodon/utils/filters.ts
@@ -1,4 +1,4 @@
-export const toServerSideType = columnType => {
+export const toServerSideType = (columnType: string) => {
   switch (columnType) {
   case 'home':
   case 'notifications':
diff --git a/app/javascript/mastodon/utils/hashtags.js b/app/javascript/mastodon/utils/hashtags.ts
similarity index 100%
rename from app/javascript/mastodon/utils/hashtags.js
rename to app/javascript/mastodon/utils/hashtags.ts
diff --git a/app/javascript/mastodon/utils/numbers.js b/app/javascript/mastodon/utils/numbers.ts
similarity index 71%
rename from app/javascript/mastodon/utils/numbers.js
rename to app/javascript/mastodon/utils/numbers.ts
index fa3d58fad1..35af8a973c 100644
--- a/app/javascript/mastodon/utils/numbers.js
+++ b/app/javascript/mastodon/utils/numbers.ts
@@ -1,23 +1,19 @@
-// @ts-check
+import type { ValueOf } from '../../types/util';
 
 export const DECIMAL_UNITS = Object.freeze({
   ONE: 1,
   TEN: 10,
-  HUNDRED: Math.pow(10, 2),
-  THOUSAND: Math.pow(10, 3),
-  MILLION: Math.pow(10, 6),
-  BILLION: Math.pow(10, 9),
-  TRILLION: Math.pow(10, 12),
+  HUNDRED: 100,
+  THOUSAND: 1_000,
+  MILLION: 1_000_000,
+  BILLION: 1_000_000_000,
+  TRILLION: 1_000_000_000_000,
 });
+export type DecimalUnits = ValueOf<typeof DECIMAL_UNITS>;
 
 const TEN_THOUSAND = DECIMAL_UNITS.THOUSAND * 10;
 const TEN_MILLIONS = DECIMAL_UNITS.MILLION * 10;
 
-/**
- * @typedef {[number, number, number]} ShortNumber
- * Array of: shorten number, unit of shorten number and maximum fraction digits
- */
-
 /**
  * @param {number} sourceNumber Number to convert to short number
  * @returns {ShortNumber} Calculated short number
@@ -25,7 +21,8 @@ const TEN_MILLIONS = DECIMAL_UNITS.MILLION * 10;
  * shortNumber(5936);
  * // => [5.936, 1000, 1]
  */
-export function toShortNumber(sourceNumber) {
+export type ShortNumber = [number, DecimalUnits, 0 | 1] // Array of: shorten number, unit of shorten number and maximum fraction digits
+export function toShortNumber(sourceNumber: number): ShortNumber {
   if (sourceNumber < DECIMAL_UNITS.THOUSAND) {
     return [sourceNumber, DECIMAL_UNITS.ONE, 0];
   } else if (sourceNumber < DECIMAL_UNITS.MILLION) {
@@ -59,20 +56,16 @@ export function toShortNumber(sourceNumber) {
  * pluralReady(1793, DECIMAL_UNITS.THOUSAND)
  * // => 1790
  */
-export function pluralReady(sourceNumber, division) {
+export function pluralReady(sourceNumber: number, division: DecimalUnits): number {
   if (division == null || division < DECIMAL_UNITS.HUNDRED) {
     return sourceNumber;
   }
 
-  let closestScale = division / DECIMAL_UNITS.TEN;
+  const closestScale = division / DECIMAL_UNITS.TEN;
 
   return Math.trunc(sourceNumber / closestScale) * closestScale;
 }
 
-/**
- * @param {number} num
- * @returns {number}
- */
-export function roundTo10(num) {
+export function roundTo10(num: number): number {
   return Math.round(num * 0.1) / 0.1;
 }
diff --git a/app/javascript/types/resources.ts b/app/javascript/types/resources.ts
index 372ff7523b..3b435ad71e 100644
--- a/app/javascript/types/resources.ts
+++ b/app/javascript/types/resources.ts
@@ -1,8 +1,4 @@
-interface MastodonMap<T> {
-  get<K extends keyof T>(key: K): T[K];
-  has<K extends keyof T>(key: K): boolean;
-  set<K extends keyof T>(key: K, value: T[K]): this;
-}
+import type { MastodonMap } from './util';
 
 type AccountValues = {
   id: number;
diff --git a/app/javascript/types/util.ts b/app/javascript/types/util.ts
new file mode 100644
index 0000000000..94df0c9198
--- /dev/null
+++ b/app/javascript/types/util.ts
@@ -0,0 +1,7 @@
+export interface MastodonMap<T> {
+  get<K extends keyof T>(key: K): T[K];
+  has<K extends keyof T>(key: K): boolean;
+  set<K extends keyof T>(key: K, value: T[K]): this;
+}
+
+export type ValueOf<T> = T[keyof T];
-- 
GitLab