Skip to content
This repository was archived by the owner on Aug 3, 2026. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
b4b7d0f
Add slide element transition and timeout
ryand56 Nov 2, 2022
6596d21
Organize slides
ryand56 Nov 3, 2022
b55aa6e
Add city info local forecast
ryand56 Nov 4, 2022
e633bdd
Add music back
ryand56 Nov 4, 2022
837ec5e
Insert header info
ryand56 Nov 4, 2022
3b7e4df
Add tailwind CSS classes to city info local forecast
ryand56 Nov 4, 2022
a815ba3
Add weather info to city info local forecast
ryand56 Nov 5, 2022
f3e6713
Add weather point info
ryand56 Nov 6, 2022
090e850
Push info into extra locations
ryand56 Nov 6, 2022
b1539c3
Add language to extra locations
ryand56 Nov 6, 2022
cc49c26
Fetch extra locations
ryand56 Nov 6, 2022
2d539ec
Fetch weather info for extra locations
ryand56 Nov 6, 2022
ff7d832
Add hook documentation
ryand56 Nov 7, 2022
bd05f69
Add extra locations to header
ryand56 Nov 7, 2022
c86eed6
Fix imports
ryand56 Nov 7, 2022
e75ea47
Fix header bug and add rest of slides
ryand56 Nov 14, 2022
f9bd2c6
Fix linter
ryand56 Nov 14, 2022
960d408
Fix city info slide bug
ryand56 Nov 15, 2022
16ad4b7
Cleanup
ryand56 Nov 15, 2022
727cfbf
Set vocal in slides
ryand56 Nov 15, 2022
88f08f6
Add missing file
ryand56 Nov 15, 2022
82b1ae7
Merge branch 'main' into location-slides
ryand56 Nov 18, 2022
c6753df
Merge branch 'main' into location-slides
ryand56 Nov 19, 2022
2079eef
Merge workflow
ryand56 Nov 19, 2022
fbb9f94
[pre] Merge script change
ryand56 Nov 19, 2022
ae081c7
Merge preview workflow
ryand56 Nov 21, 2022
f85bb77
Merge workflow fix
ryand56 Nov 21, 2022
eb27d22
Return a promise for vocals and allow custom units
ryand56 Nov 21, 2022
02620f8
Merge music changes
ryand56 Dec 6, 2022
309ea56
Merge rest of music
ryand56 Dec 6, 2022
ac81dd8
[skip build] Merge CODEOWNERS file
ryand56 Dec 6, 2022
98dba3e
Move unavailable messages into files
ryand56 Dec 9, 2022
dc9ad92
Better intro handling
ryand56 Dec 9, 2022
3368c7d
Use cached init param
ryand56 Dec 9, 2022
1dbe175
Set custom slides dynamically
ryand56 Dec 10, 2022
03c894e
Marquee changes
ryand56 Dec 10, 2022
517d9b5
Insert random extra location in header
ryand56 Dec 11, 2022
ae26e45
Detect extra location function and update severe marquees
ryand56 Dec 11, 2022
1881a5f
Add TTS to severe marquees and option to mute
ryand56 Dec 12, 2022
06cf4b7
Add window check inside of cleanup function
ryand56 Dec 12, 2022
c0552d7
Lazy load individual slides
ryand56 Dec 12, 2022
4b516fb
Add suspense to lazy loading slides
ryand56 Dec 12, 2022
9d4406b
Add extended forecast boilerplate
ryand56 Dec 12, 2022
9a85cc7
Add more lazy loading and severe beeps
ryand56 Dec 12, 2022
10a1fba
Add alert colors
ryand56 Dec 16, 2022
16d4ddc
Update TTS interval
ryand56 Dec 17, 2022
0e9ca16
Add base slide component
ryand56 Dec 18, 2022
310442c
Merge latest changes
ryand56 Dec 18, 2022
4631057
Add locations to marquees, update API
ryand56 Dec 18, 2022
5a978b4
Nullish check
ryand56 Dec 18, 2022
8675cad
Ticker changes for season
ryand56 Dec 21, 2022
eac5540
Add extended forecast header
ryand56 Dec 21, 2022
6dd158e
Cleanup
ryand56 Dec 21, 2022
5390211
Add extended forecast header background
ryand56 Dec 29, 2022
e594065
[skip build] Update copyright for new year
ryand56 Dec 30, 2022
8d5bb5a
Ticker change
ryand56 Jan 27, 2023
6ac9425
Fade in item upon shift
ryand56 Jan 30, 2023
a5a25c6
Merge config file
ryand56 Jan 30, 2023
64487c0
Move extended slide into fragment
ryand56 Jan 30, 2023
5bc5e86
Merge type error fix
ryand56 Jan 31, 2023
c7c54e9
Merge latest changes
ryand56 Jan 31, 2023
5062e1b
Merge Dockerfile changes
ryand56 Jan 31, 2023
f1e070a
Merge Dockerfile fixes
ryand56 Feb 1, 2023
dadcc5e
[skip ci] Merge Docker changes
ryand56 Feb 8, 2023
fec4cae
[skip ci] Merge Docker changes
ryand56 Feb 8, 2023
6af1f58
[pre] Merge workflow changes
ryand56 Feb 17, 2023
8732a0e
[pre] Trigger upload workflow
ryand56 Feb 17, 2023
11e8c9f
[skip ci] Merge workflow changes
ryand56 Feb 17, 2023
e629498
[skip ci] Merge updated workflow action
ryand56 Feb 17, 2023
c9f9ff7
[skip ci] Merge updated workflow action
ryand56 Feb 17, 2023
a74ff70
Merge latest changes
ryand56 Jun 19, 2023
ac445dd
Update frozen lockfile
ryand56 Jun 19, 2023
1942a0e
Update username
ryand56 Jun 20, 2023
2d0ec4e
Check for vowels in severe marquee
ryand56 Jun 20, 2023
8706742
Merge latest changes
ryand56 Jul 18, 2023
7028a81
Update for Node.js 22
ryand56 May 4, 2026
a950e19
Fix lint
ryand56 May 4, 2026
e985080
Fix order of isExtraLoc
ryand56 May 4, 2026
7eb9d72
More fixes, dedicated engine for vocals playing twice
ryand56 May 5, 2026
aa646c0
Fix background properties for Tailwind V4
ryand56 May 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ jobs:
if: ${{ !startsWith(github.event.head_commit.message, '[skip build]') }}
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v6
- name: Setup pnpm
uses: pnpm/action-setup@v2
uses: pnpm/action-setup@v6
with:
version: latest
- name: Install Vercel CLI
Expand All @@ -25,7 +25,7 @@ jobs:
- name: Install Dependencies
run: pnpm i --frozen-lockfile
- name: Lint
run: pnpm run lint
run: pnpm exec eslint
- name: Build Project Artifacts
run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
- name: Deploy Project Artifacts to Vercel
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/preview-snapshot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v6
- name: Setup pnpm
uses: pnpm/action-setup@v2
uses: pnpm/action-setup@v6
with:
version: latest
- name: Install Dependencies
Expand All @@ -26,11 +26,11 @@ jobs:
NEXT_PUBLIC_IP_API_KEY: ${{ secrets.NEXT_PUBLIC_IP_API_KEY }}
NEXT_PUBLIC_WEATHER_API_KEY: ${{ secrets.NEXT_PUBLIC_WEATHER_API_KEY }}
- name: Upload Preview
uses: ryand56/r2-upload-action@v1.2
uses: ryand56/r2-upload-action@latest
with:
r2-account-id: ${{ secrets.R2_ACCOUNT_ID }}
r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }}
r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }}
r2-bucket: ${{ secrets.R2_BUCKET }}
source-dir: scripts/dist/
destination-dir: projects/weatherscan-rewritten/autopreviews/
destination-dir: projects/weatherscan-rewritten/autopreviews/
8 changes: 4 additions & 4 deletions .github/workflows/preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ jobs:
if: ${{ !startsWith(github.event.head_commit.message, '[skip build]') }}
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v6
- name: Setup pnpm
uses: pnpm/action-setup@v2
uses: pnpm/action-setup@v6
with:
version: latest
- name: Install Dependencies
run: pnpm i --frozen-lockfile
- name: Lint
run: pnpm run lint
run: pnpm exec eslint
- name: Build
run: pnpm run build
run: pnpm run build
13 changes: 3 additions & 10 deletions components/CCIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,13 @@ interface CCIconProps {
windData: number
}

const CCIcon = ({ iconCode, windData }: CCIconProps) => {
const [icon, setIcon] = React.useState<number>(Icons2010.UNK);

React.useEffect(() => {
if (typeof iconCode === "number" && typeof windData === "number") {
const mapped = getIcon(iconCode, windData);
setIcon(mapped);
}
}, [iconCode, windData]);
const CCIcon = ({ iconCode = 44, windData = 0 }: CCIconProps) => {
const icon = getIcon(iconCode, windData);

return (
<div
id="conditions-icon"
className="absolute left-conditions-icon-l bg-conditions-icon w-conditions-icon h-conditions-icon bg-no-repeat top-conditions-icon-t z-0"
className="absolute left-conditions-icon-l w-conditions-icon h-conditions-icon bg-no-repeat bg-center bg-cover top-conditions-icon-t z-0"
style={{ backgroundImage: `url(images/icons2010/${icon < 10 ? `0${icon}` : icon}.png)` }}
/>
);
Expand Down
44 changes: 20 additions & 24 deletions components/Current.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,34 @@ interface CurrentProps {
}

const Current = ({ temp, info }: CurrentProps) => {
const [cycle, setCycle] = React.useState<string[]>([]);
const cycle = React.useMemo(() => {
if (!info || info.phrase === "") {
return [];
}

return [
`visibility ${info.visib} ${info.visib != 1 ? "miles" : "mile"}`,
`UV index ${info.uvIndex}`,
info.phrase,
`wind ${info.wind}`,
`humidity ${info.humidity}%`,
`dew point ${info.dewpt}°`,
`pressure ${info.pres}`
];
}, [info]);

const [idx, setIdx] = React.useState<number>(0);
const [infoMsg, setInfoMsg] = React.useState<string>("");
const infoMsg = cycle[idx] ?? "";

React.useEffect(() => {
let intervalTimer: NodeJS.Timeout;
if (info) {
if (info.phrase !== "") {
const tempCycle = [
`visibility ${info.visib} ${info.visib != 1 ? "miles" : "mile"}`,
`UV index ${info.uvIndex}`,
info.phrase,
`wind ${info.wind}`,
`humidity ${info.humidity}%`,
`dew point ${info.dewpt}°`,
`pressure ${info.pres}`
];

setCycle(tempCycle);
if (cycle.length === 0) return;

intervalTimer = setInterval(() => {
setIdx((idx) => {
if (idx >= (tempCycle.length - 1)) {
if (idx >= (cycle.length - 1)) {
return 0;
} else {
return idx + 1;
Expand All @@ -40,16 +45,7 @@ const Current = ({ temp, info }: CurrentProps) => {
}

return () => clearInterval(intervalTimer);
}, [info]);

React.useEffect(() => {
if (cycle) {
if (cycle.length > 0) {
const msg = cycle[idx];
setInfoMsg(msg);
}
}
}, [idx]);
}, [info, cycle.length]);

return (
<div id="current-conditions" className="font-interstate absolute top-current-t left-0 h-current w-current text-left z-current">
Expand Down
102 changes: 46 additions & 56 deletions components/CustomMarquee/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,69 +40,59 @@ const CustomMarquee = ({
onCycleComplete,
children
}: CustomMarqueeProps) => {
const [isMounted, setIsMounted] = React.useState<boolean>(false);

React.useEffect(() => {
setIsMounted(true);
}, []);

const rgbaGradientColor = `rgba(${gradientColor[0]}, ${gradientColor[1]}, ${gradientColor[2]})`;

return (
<>
{!isMounted ? null : (
<div
style={{
...style,
["--pause-on-hover" as string]: !play || pauseOnHover ? "paused" : "running",
["--pause-on-click" as string]: !play || (pauseOnHover && !pauseOnClick) || pauseOnClick ? "paused" : "running"
}}
className={styles["marquee-container"] + (className !== "" ? ` ${className}` : "")}
>
{gradient && (
<div
style={{
...style,
["--pause-on-hover" as string]: !play || pauseOnHover ? "paused" : "running",
["--pause-on-click" as string]: !play || (pauseOnHover && !pauseOnClick) || pauseOnClick ? "paused" : "running"
["--gradient-color" as string]: `${rgbaGradientColor}, 1), ${rgbaGradientColor}, 0)`,
["--gradient-width" as string]:
typeof gradientWidth === "number"
? `${gradientWidth}px`
: gradientWidth,
}}
className={styles["marquee-container"] + (className !== "" ? ` ${className}` : "")}
>
{gradient && (
<div
style={{
["--gradient-color" as string]: `${rgbaGradientColor}, 1), ${rgbaGradientColor}, 0)`,
["--gradient-width" as string]:
typeof gradientWidth === "number"
? `${gradientWidth}px`
: gradientWidth,
}}
className={styles.overlay}
/>
)}
<div
style={{
["--play" as string]: play ? "running" : "paused",
["--direction" as string]:
direction === "left" ? "normal" : "reverse",
["--duration" as string]: `${duration}s`,
["--delay" as string]: `${delay}s`,
["--iteration-count" as string]: !!loop ? `${loop}` : "infinite",
}}
className={styles.marquee}
onAnimationIteration={onCycleComplete}
onAnimationEnd={onFinish}
>
{children}
</div>
<div
style={{
["--play" as string]: play ? "running" : "paused",
["--direction" as string]:
direction === "left" ? "normal" : "reverse",
["--duration" as string]: `${duration}s`,
["--delay" as string]: `${delay}s`,
["--iteration-count" as string]: !!loop ? `${loop}` : "infinite",
}}
className={styles.marquee}
aria-hidden="true"
>
{children}
</div>
</div>
className={styles.overlay}
/>
)}
</>
<div
style={{
["--play" as string]: play ? "running" : "paused",
["--direction" as string]:
direction === "left" ? "normal" : "reverse",
["--duration" as string]: `${duration}s`,
["--delay" as string]: `${delay}s`,
["--iteration-count" as string]: !!loop ? `${loop}` : "infinite",
}}
className={styles.marquee}
onAnimationIteration={onCycleComplete}
onAnimationEnd={onFinish}
>
{children}
</div>
<div
style={{
["--play" as string]: play ? "running" : "paused",
["--direction" as string]:
direction === "left" ? "normal" : "reverse",
["--duration" as string]: `${duration}s`,
["--delay" as string]: `${delay}s`,
["--iteration-count" as string]: !!loop ? `${loop}` : "infinite",
}}
className={styles.marquee}
aria-hidden="true"
>
{children}
</div>
</div>
);
};

Expand Down
49 changes: 30 additions & 19 deletions components/DateTime.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,47 @@
import * as React from "react";
import { useRouter } from "next/router";

interface DateTimeProps {
tz: string
}

const DateTime = ({ tz }: DateTimeProps) => {
const router = useRouter();
const [date, setDate] = React.useState<string>("Jan 01");
const [time, setTime] = React.useState<string>("12:00:00pm");

const updateTime = () => {
const date = new Date();

const formatDate = date.toString().slice(4, 10).trimEnd();
const formatTime = date.toLocaleTimeString("en-US", {
hour: "numeric",
hour12: true,
minute: "numeric",
second: "numeric",
timeZone: tz
}).replace(/ /g, "").toLowerCase();

setDate(formatDate);
setTime(formatTime);
const stdTimezoneOffset = (date: Date) => {
var jan = new Date(date.getFullYear(), 0, 1);
var jul = new Date(date.getFullYear(), 6, 1);
return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
};

const isDstObserved = (date: Date) => {
return date.getTimezoneOffset() < stdTimezoneOffset(date);
};

React.useEffect(() => {
let interval: NodeJS.Timeout;
if (tz === "") return;

const update = () => {
const date = new Date();

const formatDate = date.toString().slice(4, 10).trimEnd();
const formatTime = date.toLocaleTimeString("en-US", {
hour: "numeric",
hour12: true,
minute: "numeric",
second: "numeric",
timeZone: tz
}).replace(/ /g, "").toLowerCase();

setDate(formatDate);
setTime(formatTime);
};

update();

if (tz !== "") {
updateTime();
interval = setInterval(updateTime, 500);
}
const interval = setInterval(update, 500);

return () => clearInterval(interval);
}, [tz]);
Expand Down
Loading