diff --git a/src/App.tsx b/src/App.tsx index 3063c3533b..151fbbabd0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -27,12 +27,12 @@ import { UpdateContextProvider } from "./pages/settings/update/UpdateContext"; import GlobalStyles from "./GlobalStyles"; import GalleryProvider from "./features/gallery/GalleryProvider"; import ConfigProvider from "./services/app"; +import { getDeviceMode } from "./features/settings/settingsSlice"; setupIonicReact({ rippleEffect: false, - mode: "ios", - swipeBackEnabled: isInstalled(), - hardwareBackButton: true, + mode: getDeviceMode(), + swipeBackEnabled: isInstalled() && getDeviceMode() === "ios", }); export default function App() { diff --git a/src/TabbedRoutes.tsx b/src/TabbedRoutes.tsx index 1d9136ff88..0d6f9a4c55 100644 --- a/src/TabbedRoutes.tsx +++ b/src/TabbedRoutes.tsx @@ -57,6 +57,7 @@ import BlocksSettingsPage from "./pages/settings/BlocksSettingsPage"; import { getDefaultServer } from "./services/app"; import GeneralPage from "./pages/settings/GeneralPage"; import HidingSettingsPage from "./pages/settings/HidingSettingsPage"; +import DeviceModeSettingsPage from "./pages/settings/DeviceModeSettingsPage"; const Interceptor = styled.div` position: absolute; @@ -335,6 +336,9 @@ export default function TabbedRoutes() { + + + diff --git a/src/features/settings/appearance/system/DarkMode.tsx b/src/features/settings/appearance/system/DarkMode.tsx index 6c35ee8ca3..033e0d1376 100644 --- a/src/features/settings/appearance/system/DarkMode.tsx +++ b/src/features/settings/appearance/system/DarkMode.tsx @@ -1,8 +1,7 @@ -import { IonLabel, IonList, IonToggle } from "@ionic/react"; +import { IonLabel, IonToggle } from "@ionic/react"; import { InsetIonItem } from "../../../../pages/profile/ProfileFeedItemsPage"; import { useAppDispatch, useAppSelector } from "../../../../store"; import { setUseSystemDarkMode } from "../../settingsSlice"; -import UserDarkMode from "./UserDarkMode"; export default function DarkMode() { const dispatch = useAppDispatch(); @@ -11,20 +10,12 @@ export default function DarkMode() { ); return ( - <> - - - Use System Light/Dark Mode - - dispatch(setUseSystemDarkMode(e.detail.checked)) - } - /> - - - - {!usingSystemDarkMode && } - + + Use System Light/Dark Mode + dispatch(setUseSystemDarkMode(e.detail.checked))} + /> + ); } diff --git a/src/features/settings/appearance/system/DeviceMode.tsx b/src/features/settings/appearance/system/DeviceMode.tsx new file mode 100644 index 0000000000..63db833560 --- /dev/null +++ b/src/features/settings/appearance/system/DeviceMode.tsx @@ -0,0 +1,30 @@ +import { Mode } from "@ionic/core"; +import { useAppSelector } from "../../../../store"; +import { InsetIonItem } from "../../../user/Profile"; +import { IonLabel } from "@ionic/react"; + +export default function DeviceMode() { + const deviceMode = useAppSelector( + (state) => state.settings.appearance.deviceMode + ); + + return ( + <> + + Device Mode + + {getDeviceModeLabel(deviceMode)} + + + + ); +} + +export function getDeviceModeLabel(mode: Mode): string { + switch (mode) { + case "ios": + return "Apple"; + case "md": + return "Android (beta)"; + } +} diff --git a/src/features/settings/appearance/system/SelectDeviceMode.tsx b/src/features/settings/appearance/system/SelectDeviceMode.tsx new file mode 100644 index 0000000000..6139005967 --- /dev/null +++ b/src/features/settings/appearance/system/SelectDeviceMode.tsx @@ -0,0 +1,49 @@ +import { IonLabel, IonList, IonRadio, IonRadioGroup } from "@ionic/react"; +import { InsetIonItem } from "../../../user/Profile"; +import { getDeviceModeLabel } from "./DeviceMode"; +import { useAppDispatch, useAppSelector } from "../../../../store"; +import { useState } from "react"; +import { setDeviceMode } from "../../settingsSlice"; + +const MODES = ["ios", "md"] as const; + +export default function SelectDeviceMode() { + const dispatch = useAppDispatch(); + const deviceMode = useAppSelector( + (state) => state.settings.appearance.deviceMode + ); + const [selectedDeviceMode, setSelectedDeviceMode] = useState(deviceMode); + + function apply() { + dispatch(setDeviceMode(selectedDeviceMode)); + location.reload(); + } + return ( + <> + setSelectedDeviceMode(e.detail.value)} + > + + {MODES.map((mode) => ( + setSelectedDeviceMode(mode)} + > + {getDeviceModeLabel(mode)} + + + ))} + + + + {selectedDeviceMode !== deviceMode && ( + + + Tap to apply changes and reload app + + + )} + + ); +} diff --git a/src/features/settings/appearance/system/System.tsx b/src/features/settings/appearance/system/System.tsx index eca7afc0a0..03aada0b90 100644 --- a/src/features/settings/appearance/system/System.tsx +++ b/src/features/settings/appearance/system/System.tsx @@ -1,14 +1,26 @@ -import { IonLabel } from "@ionic/react"; +import { IonLabel, IonList } from "@ionic/react"; import DarkMode from "./DarkMode"; import { ListHeader } from "../TextSize"; +import DeviceMode from "./DeviceMode"; +import { useAppSelector } from "../../../../store"; +import UserDarkMode from "./UserDarkMode"; export default function System() { + const { usingSystemDarkMode } = useAppSelector( + (state) => state.settings.appearance.dark + ); + return ( <> System - + + + + + + {!usingSystemDarkMode && } ); } diff --git a/src/features/settings/settingsSlice.tsx b/src/features/settings/settingsSlice.tsx index 73afedb000..43641f88fd 100644 --- a/src/features/settings/settingsSlice.tsx +++ b/src/features/settings/settingsSlice.tsx @@ -21,6 +21,7 @@ import { OCommentDefaultSort, } from "../../services/db"; import { get, set } from "./storage"; +import { Mode } from "@ionic/core"; export { type CommentThreadCollapse, @@ -50,6 +51,7 @@ interface SettingsState { usingSystemDarkMode: boolean; userDarkMode: boolean; }; + deviceMode: Mode; }; general: { comments: { @@ -72,6 +74,7 @@ const LOCALSTORAGE_KEYS = { USE_SYSTEM: "appearance--dark-use-system", USER_MODE: "appearance--dark-user-mode", }, + DEVICE_MODE: "appearance--device-mode", } as const; const initialState: SettingsState = { @@ -93,6 +96,7 @@ const initialState: SettingsState = { usingSystemDarkMode: true, userDarkMode: false, }, + deviceMode: "ios", }, general: { comments: { @@ -118,6 +122,7 @@ const stateWithLocalstorageItems: SettingsState = merge(initialState, { usingSystemDarkMode: get(LOCALSTORAGE_KEYS.DARK.USE_SYSTEM), userDarkMode: get(LOCALSTORAGE_KEYS.DARK.USER_MODE), }, + deviceMode: get(LOCALSTORAGE_KEYS.DEVICE_MODE), }, }); @@ -194,6 +199,11 @@ export const appearanceSlice = createSlice({ set(LOCALSTORAGE_KEYS.DARK.USE_SYSTEM, action.payload); }, + setDeviceMode(state, action: PayloadAction) { + state.appearance.deviceMode = action.payload; + + set(LOCALSTORAGE_KEYS.DEVICE_MODE, action.payload); + }, setDefaultCommentSort(state, action: PayloadAction) { state.general.comments.sort = action.payload; @@ -331,6 +341,7 @@ export const { setShowVotingButtons, setUserDarkMode, setUseSystemDarkMode, + setDeviceMode, setDefaultCommentSort, settingsReady, setDisableMarkingPostsRead, @@ -338,3 +349,8 @@ export const { } = appearanceSlice.actions; export default appearanceSlice.reducer; + +export function getDeviceMode(): Mode { + // md mode is beta, so default ios for all devices + return get(LOCALSTORAGE_KEYS.DEVICE_MODE) ?? "ios"; +} diff --git a/src/pages/settings/DeviceModeSettingsPage.tsx b/src/pages/settings/DeviceModeSettingsPage.tsx new file mode 100644 index 0000000000..1f3f9fe4b7 --- /dev/null +++ b/src/pages/settings/DeviceModeSettingsPage.tsx @@ -0,0 +1,32 @@ +import { + IonBackButton, + IonButtons, + IonHeader, + IonPage, + IonTitle, + IonToolbar, +} from "@ionic/react"; +import AppContent from "../../features/shared/AppContent"; +import SelectDeviceMode from "../../features/settings/appearance/system/SelectDeviceMode"; + +export default function DeviceModeSettingsPage() { + return ( + + + + + + + + Device Mode + + + + + + + ); +} diff --git a/src/theme/variables.ts b/src/theme/variables.ts index 8b11ad5d75..49bb467007 100644 --- a/src/theme/variables.ts +++ b/src/theme/variables.ts @@ -252,7 +252,7 @@ export const darkVariables = css` // Material Design Dark Theme .md body { - --ion-background-color: #121212; + --ion-background-color: black; --ion-background-color-rgb: 18, 18, 18; --ion-text-color: #ffffff; @@ -260,7 +260,7 @@ export const darkVariables = css` --ion-border-color: #222222; - --ion-color-step-50: #1e1e1e; + --ion-color-step-50: #121212; --ion-color-step-100: #2a2a2a; --ion-color-step-150: #363636; --ion-color-step-200: #414141; @@ -280,13 +280,16 @@ export const darkVariables = css` --ion-color-step-900: #e7e7e7; --ion-color-step-950: #f3f3f3; - --ion-item-background: #1e1e1e; + --ion-item-background: black; --ion-toolbar-background: #1f1f1f; --ion-tab-bar-background: #1f1f1f; - --ion-card-background: #1e1e1e; + --ion-card-background: black; + + --ion-toolbar-background: #121212; + --ion-tab-bar-background: #121212; } @media (max-width: 767px) {