Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
99 changes: 99 additions & 0 deletions src/Startpage/Clock/Clock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { useEffect, useState } from "react"

import styled from "@emotion/styled"

import * as Settings from "../Settings/settingsHandler"

const Greeting = styled.div`
font-size: 14px;
letter-spacing: 1px;
color: var(--accent-color);
`

const Time = styled.div`
font-size: 32px;
font-weight: 500;
font-variant-numeric: tabular-nums;
`

const DateLabel = styled.div`
font-size: 13px;
letter-spacing: 0.5px;
opacity: 0.7;
`

const ClockContainer = styled.div`
position: fixed;
top: 20px;
left: 24px;
display: flex;
flex-direction: column;
line-height: 1.15;
color: var(--default-color);
opacity: 0.5;
transition: 0.3s;
user-select: none;

:hover {
opacity: 1;

.clock-time {
animation: text-flicker 0.01s ease 0s infinite alternate;
}
}
`

const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
const months = [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
]

const pad = (value: number) => String(value).padStart(2, "0")

// Boundaries are subjective — tweak to taste.
const greetingFor = (hour: number) => {
if (hour < 5) return "Good night"
if (hour < 12) return "Good morning"
if (hour < 17) return "Good afternoon"
if (hour < 21) return "Good evening"
return "Good night"
}

export const Clock = () => {
const [now, setNow] = useState(() => new Date())
const [settings] = useState(() => Settings.Clock.getWithFallback())

useEffect(() => {
const id = setInterval(() => setNow(new Date()), 1000)
return () => clearInterval(id)
}, [])

return (
<ClockContainer>
{settings.showGreeting && (
<Greeting>{greetingFor(now.getHours())}</Greeting>
)}
{settings.showTime && (
<Time className="clock-time">
{pad(now.getHours())}:{pad(now.getMinutes())}
</Time>
)}
{settings.showDate && (
<DateLabel>
{days[now.getDay()]}, {now.getDate()} {months[now.getMonth()]}
</DateLabel>
)}
</ClockContainer>
)
}
48 changes: 48 additions & 0 deletions src/Startpage/Settings/ClockSettings/ClockSettings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { ToggleOption } from "../../../components/ToggleOption"
import { ClockSettings as ClockSettingsType } from "../../../data/data"
import {
StyledSettingsContent,
SettingElement,
SettingsLabel,
} from "../SettingsWindow"

interface props {
clockSettings: ClockSettingsType
setClockSettings: (clockSettings: ClockSettingsType) => void
}

export const ClockSettings = ({ clockSettings, setClockSettings }: props) => (
<StyledSettingsContent>
<SettingsLabel>Clock</SettingsLabel>

<SettingElement>
<ToggleOption
label="Disable greeting"
checked={!clockSettings.showGreeting}
onChange={disabled =>
setClockSettings({ ...clockSettings, showGreeting: !disabled })
}
/>
</SettingElement>

<SettingElement>
<ToggleOption
label="Disable time"
checked={!clockSettings.showTime}
onChange={disabled =>
setClockSettings({ ...clockSettings, showTime: !disabled })
}
/>
</SettingElement>

<SettingElement>
<ToggleOption
label="Disable date"
checked={!clockSettings.showDate}
onChange={disabled =>
setClockSettings({ ...clockSettings, showDate: !disabled })
}
/>
</SettingElement>
</StyledSettingsContent>
)
14 changes: 13 additions & 1 deletion src/Startpage/Settings/SettingsWindow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
} from "@fortawesome/free-solid-svg-icons"

import { Changelog } from "./Changelog/Changelog"
import { ClockSettings } from "./ClockSettings/ClockSettings"
import { DesignSettings } from "./DesignSettings/DesignSettings"
import { LinkSettings } from "./LinkSettings/LinkSettings"
import { SearchSettings } from "./SearchSettings/SearchSettings"
Expand Down Expand Up @@ -123,7 +124,7 @@ const TabOption = styled.button<{ active: boolean }>`
}
`

const TabOptions = ["Links", "Appearance", "Searchbar", "Changelog"]
const TabOptions = ["Links", "Appearance", "Searchbar", "Clock", "Changelog"]

interface props {
hidePopup: () => void
Expand All @@ -137,12 +138,16 @@ export const SettingsWindow = ({ hidePopup }: props) => {
const [searchSettings, setSearchSettings] = useState(
Settings.Search.getWithFallback()
)
const [clockSettings, setClockSettings] = useState(
Settings.Clock.getWithFallback()
)

const applyValues = () => {
Settings.Design.set(design)
Settings.Themes.set(themes)
Settings.Search.set(searchSettings)
Settings.Links.set(linkGroups)
Settings.Clock.set(clockSettings)
window.location.reload()
}

Expand Down Expand Up @@ -184,6 +189,13 @@ export const SettingsWindow = ({ hidePopup }: props) => {
/>
)}

{currentTab === "Clock" && (
<ClockSettings
clockSettings={clockSettings}
setClockSettings={setClockSettings}
/>
)}

{currentTab === "Changelog" && <Changelog />}
</WindowContent>

Expand Down
25 changes: 25 additions & 0 deletions src/Startpage/Settings/settingsHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,36 @@ import {
linkGroup,
Theme,
Search as SearchType,
ClockSettings as ClockType,
links,
searchSettings,
clockSettings,
themes,
} from "../../data/data"

export const Clock = {
get: () => {
const lsClock = localStorage.getItem("clock-settings")
if (lsClock) return Clock.parse(lsClock)
return undefined
},
getWithFallback: () => {
try {
return Clock.get() ?? clockSettings
} catch {
console.error(
"Your currently applied clock settings appear to be corrupted."
)
return clockSettings
}
},

set: (clockSettings: ClockType) =>
localStorage.setItem("clock-settings", JSON.stringify(clockSettings)),

parse: (clockSettings: string) => JSON.parse(clockSettings) as ClockType,
}

export const Search = {
get: () => {
const lsSearch = localStorage.getItem("search-settings")
Expand Down
2 changes: 2 additions & 0 deletions src/Startpage/Startpage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useState } from "react"

import styled from "@emotion/styled"

import { Clock } from "./Clock/Clock"
import { LinkContainer } from "./LinkContainer/LinkContainer"
import { Searchbar } from "./Searchbar/Searchbar"
import { Settings } from "./Settings/Settings"
Expand Down Expand Up @@ -47,6 +48,7 @@ export const Startpage = () => {
<LinkContainer />
</StyledStartpage>
<Searchbar />
<Clock />
<Settings />
</Wrapper>
)
Expand Down
40 changes: 40 additions & 0 deletions src/components/ToggleOption.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import styled from "@emotion/styled"

const ToggleLabel = styled.label`
display: flex;
align-items: center;
gap: 8px;
width: max-content;
color: var(--default-color);
cursor: pointer;
user-select: none;
transition: 0.3s;

:hover {
animation: circling-shadow-small 2s ease 0s infinite normal;
}
`

const ToggleCheckbox = styled.input`
width: 16px;
height: 16px;
accent-color: var(--accent-color);
cursor: pointer;
`

type props = {
label: string
checked: boolean
onChange: (checked: boolean) => void
}

export const ToggleOption = ({ label, checked, onChange }: props) => (
<ToggleLabel>
<ToggleCheckbox
type="checkbox"
checked={checked}
onChange={e => onChange(e.target.checked)}
/>
{label}
</ToggleLabel>
)
12 changes: 12 additions & 0 deletions src/data/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,18 @@ export const searchSettings: Search = {
},
}

export interface ClockSettings {
showGreeting: boolean
showTime: boolean
showDate: boolean
}

export const clockSettings: ClockSettings = {
showGreeting: true,
showTime: true,
showDate: true,
}

export interface colorsType {
[key: string]: string
"--bg-color": string
Expand Down