diff --git a/src/components/AutoOrientingClock.tsx b/src/components/AutoOrientingClock.tsx new file mode 100644 --- /dev/null +++ b/src/components/AutoOrientingClock.tsx @@ -0,0 +1,55 @@ +// Copyright (c) 2025 Joseph Hale +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +import { useState } from "react"; +import { useSettings } from "../settings/useSettings"; +import Orientation from "../utils/orientation"; +import { StyleSheet, View } from "react-native"; +import BinaryClock from "./BinaryClock"; + + +export default function AutoOrientingClock({ lastAspectUpdate }: { lastAspectUpdate: Date }) { + const [settings] = useSettings('AutoOrientingClock'); + const [layout, setLayout] = useState({ + height: 0, + width: 0, + date: new Date(0), + }); + const showClock = + layout.height > 0 && + layout.width > 0 && + layout.date.getTime() > lastAspectUpdate.getTime(); + const orientation = + layout.height > layout.width ? Orientation.Portrait : Orientation.Landscape; + return ( + { + setLayout({ + height: nativeEvent.layout.height, + width: nativeEvent.layout.width, + date: new Date(), + }); + }}> + {!showClock ? ( + + ) : ( + + )} + + ); +} + +const styles = StyleSheet.create({ + blankClock: { + height: '100%', + backgroundColor: 'black', + } +}) \ No newline at end of file diff --git a/src/pages/BinaryClockScreen.tsx b/src/pages/BinaryClockScreen.tsx --- a/src/pages/BinaryClockScreen.tsx +++ b/src/pages/BinaryClockScreen.tsx @@ -1,154 +1,59 @@ -// Copyright (c) 2022 Joseph Hale +// Copyright (c) 2022 - 2025 Joseph Hale // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// file, You can obtain one at https://mozilla.org/MPL/2.0/. import { Pressable, SafeAreaView, - ScrollView, StyleSheet, View, - useWindowDimensions, + useWindowDimensions } from 'react-native'; -import React, {useCallback, useState} from 'react'; +import React, { useCallback, useState } from 'react'; -import BinaryClock from '../components/BinaryClock'; -import Orientation from '../utils/orientation'; -import SettingBoolean from '../components/settings/SettingBoolean'; -import SettingRange from '../components/settings/SettingRange'; -import { useSettings } from '../settings/useSettings'; +import AutoOrientingClock from '../components/AutoOrientingClock'; +import SettingsScrollView from '../components/settings/SettingsScrollView'; -const BinaryClockScreen: React.FC = () => { - const [showSettings, setShowSettings] = useState<{ - value: boolean; - updated: Date; - }>({value: false, updated: new Date()}); - const toggleSettings = useCallback( - () => setShowSettings({value: !showSettings.value, updated: new Date()}), - [showSettings], - ); - const {height, width} = useWindowDimensions(); - const [settings, updateSetting] = useSettings('BinaryClockScreen'); - const brightnessString = `${Math.round(settings.brightness * 100)}%`; - const roundnessString = `${Math.round(settings.roundness * 100)}%`; +function BinaryClockScreen() { + const [settingsVisibility, toggleSettingsVisibility] = useSettingsVisibility(); + + const { height, width } = useWindowDimensions(); + const flexStyle = { flexDirection: height > width ? 'column' : 'row' } as const + return ( - width ? 'column' : 'row'}, - ]}> - - + + + - {showSettings.value && ( - - updateSetting({brightness: value})} - caption={brightnessString} - /> - updateSetting({roundness: value})} - caption={roundnessString} - /> - updateSetting({showHints: value})} - initialValue={settings.showHints} - /> - + {settingsVisibility.value && ( + + + )} ); }; -function Clock({ - brightness, - roundness, - showHints, - lastAspectUpdate, -}: { - brightness: number; - roundness: number; - showHints: boolean; - lastAspectUpdate: Date; -}) { - const [layout, setLayout] = useState({ - height: 0, - width: 0, - date: new Date(0), - }); - const showClock = - layout.height > 0 && - layout.width > 0 && - layout.date.getTime() > lastAspectUpdate.getTime(); - const orientation = - layout.height > layout.width ? Orientation.Portrait : Orientation.Landscape; - return ( - { - setLayout({ - height: nativeEvent.layout.height, - width: nativeEvent.layout.width, - date: new Date(), - }); - }}> - {!showClock ? ( - - ) : ( - - )} - +function useSettingsVisibility() { + const [visibility, setVisibility] = useState<{ + value: boolean; + updated: Date; + }>({ value: false, updated: new Date() }); + const toggleVisibility = useCallback( + () => setVisibility({ value: !visibility.value, updated: new Date() }), + [visibility], ); + return [visibility, toggleVisibility] as const; } const styles = StyleSheet.create({ - container: { - height: '100%', - }, - clockPreview: { - flex: 2, - }, - blankClock: { - height: '100%', - backgroundColor: 'black', - }, - settingsContainer: { - flex: 3, - }, - settingsContentContainer: { - padding: 20, - justifyContent: 'flex-start', - }, - label: { - fontSize: 20, - fontWeight: 'bold', - marginBottom: 10, - }, - description: { - marginBottom: 10, - }, + container: { height: '100%' }, + clock: { flex: 5 }, + settings: { flex: 2 }, }); export default BinaryClockScreen; diff --git a/src/components/settings/SettingsScrollView.tsx b/src/components/settings/SettingsScrollView.tsx new file mode 100644 --- /dev/null +++ b/src/components/settings/SettingsScrollView.tsx @@ -0,0 +1,46 @@ +// Copyright (c) 2025 Joseph Hale +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +import { ScrollView, StyleSheet } from "react-native"; +import { useSettings } from "../../settings/useSettings"; +import SettingRange from "./SettingRange"; +import SettingBoolean from "./SettingBoolean"; + + +export default function SettingsScrollView() { + const [settings, updateSetting] = useSettings('SettingsScrollView'); + const brightnessString = `${Math.round(settings.brightness * 100)}%`; + const roundnessString = `${Math.round(settings.roundness * 100)}%`; + return ( + + updateSetting({ brightness: value })} + caption={brightnessString} + /> + updateSetting({ roundness: value })} + caption={roundnessString} + /> + updateSetting({ showHints: value })} + initialValue={settings.showHints} + /> + + ) +} + +const styles = StyleSheet.create({ + contentContainer: { + padding: 20, + justifyContent: 'flex-start', + }, +}) \ No newline at end of file