add dark mode

This commit is contained in:
keyan 2021-11-04 19:07:41 -04:00
parent 2d97314d33
commit 3bbf3f7470
8 changed files with 72 additions and 25 deletions

View File

@ -44,6 +44,15 @@ export default {
return true return true
}, },
setTheme: async (parent, { theme }, { me, models }) => {
if (!me) {
throw new AuthenticationError('you must be logged in')
}
await models.user.update({ where: { id: me.id }, data: { theme } })
return true
},
upsertBio: async (parent, { bio }, { me, models }) => { upsertBio: async (parent, { bio }, { me, models }) => {
if (!me) { if (!me) {
throw new AuthenticationError('you must be logged in') throw new AuthenticationError('you must be logged in')

View File

@ -11,6 +11,7 @@ export default gql`
extend type Mutation { extend type Mutation {
setName(name: String!): Boolean setName(name: String!): Boolean
setSettings(tipDefault: Int!): Boolean setSettings(tipDefault: Int!): Boolean
setTheme(theme: String!): Boolean
upsertBio(bio: String!): User! upsertBio(bio: String!): User!
} }
@ -29,5 +30,6 @@ export default gql`
bio: Item bio: Item
sats: Int! sats: Int!
msats: Int! msats: Int!
theme: String!
} }
` `

View File

@ -13,6 +13,8 @@ import { useEffect, useState } from 'react'
import { randInRange } from '../lib/rand' import { randInRange } from '../lib/rand'
import styled from 'styled-components' import styled from 'styled-components'
import Sun from '../svgs/sun-fill.svg' import Sun from '../svgs/sun-fill.svg'
import Moon from '../svgs/moon-fill.svg'
import { gql, useMutation } from '@apollo/client'
const Brand = styled(Navbar.Brand)` const Brand = styled(Navbar.Brand)`
color: ${({ theme }) => theme.brandColor} color: ${({ theme }) => theme.brandColor}
@ -43,6 +45,16 @@ export const StyledNavbar = styled(Navbar).attrs(({ theme }) => ({
& .dropdown-divider { & .dropdown-divider {
border-top: 1px solid ${({ theme }) => theme.borderColor}; border-top: 1px solid ${({ theme }) => theme.borderColor};
} }
& .theme {
margin-right: 1rem;
cursor: pointer;
fill: ${({ theme }) => theme.dropdownItemColor};
}
& .theme:hover {
fill: ${({ theme }) => theme.dropdownItemColorHover};
}
` `
function WalletSummary ({ me }) { function WalletSummary ({ me }) {
@ -56,6 +68,12 @@ export default function Header () {
const [session, loading] = useSession() const [session, loading] = useSession()
const [sort, setSort] = useState('recent') const [sort, setSort] = useState('recent')
const [within, setWithin] = useState() const [within, setWithin] = useState()
const [setTheme] = useMutation(
gql`
mutation setTheme($theme: String!) {
setTheme(theme: $theme)
}`
)
useEffect(() => { useEffect(() => {
setSort(localStorage.getItem('sort') || 'recent') setSort(localStorage.getItem('sort') || 'recent')
@ -127,7 +145,9 @@ export default function Header () {
<Link href='/settings' passHref> <Link href='/settings' passHref>
<NavDropdown.Item>settings</NavDropdown.Item> <NavDropdown.Item>settings</NavDropdown.Item>
</Link> </Link>
<Sun className='fill-grey mr-3' /> {me?.theme === 'light'
? <Moon onClick={() => setTheme({ variables: { theme: 'dark' } })} className='theme' />
: <Sun onClick={() => setTheme({ variables: { theme: 'light' } })} className='theme' />}
</div> </div>
<NavDropdown.Divider /> <NavDropdown.Divider />
<NavDropdown.Item onClick={signOut}>logout</NavDropdown.Item> <NavDropdown.Item onClick={signOut}>logout</NavDropdown.Item>

View File

@ -21,6 +21,7 @@ export function MeProvider ({ children }) {
id id
} }
hasInvites hasInvites
theme
} }
}` }`
const { data } = useQuery(query, { pollInterval: 1000 }) const { data } = useQuery(query, { pollInterval: 1000 })

View File

@ -2,7 +2,7 @@ import '../styles/globals.scss'
import { ApolloProvider, gql } from '@apollo/client' import { ApolloProvider, gql } from '@apollo/client'
import { Provider } from 'next-auth/client' import { Provider } from 'next-auth/client'
import { FundErrorModal, FundErrorProvider } from '../components/fund-error' import { FundErrorModal, FundErrorProvider } from '../components/fund-error'
import { MeProvider } from '../components/me' import { MeProvider, useMe } from '../components/me'
import PlausibleProvider from 'next-plausible' import PlausibleProvider from 'next-plausible'
import { LightningProvider } from '../components/lightning' import { LightningProvider } from '../components/lightning'
import { ItemActModal, ItemActProvider } from '../components/item-act' import { ItemActModal, ItemActProvider } from '../components/item-act'
@ -60,20 +60,18 @@ const GlobalStyle = createGlobalStyle`
} }
` `
// const lightTheme = { const lightTheme = {
// body: 'linear-gradient(180deg, #f5f5f5, #f5f5f5, white)', body: '#f5f5f5',
// color: '#212529', color: '#212529',
// navbarVariant: 'light', navbarVariant: 'light',
// inputBg: '#ffffff', borderColor: '#ced4da',
// navbarVariant: 'light', inputBg: '#ffffff',
// borderColor: 'rgb(255 255 255 / 50%)', dropdownItemColor: 'inherit',
// dropdownItemColor: 'rgba(255, 255, 255, 0.7)', dropdownItemColorHover: 'rgba(0, 0, 0, 0.9)',
// dropdownItemColorHover: 'rgba(255, 255, 255, 0.9)', commentBg: 'rgba(0, 0, 0, 0.03)',
// commentBg: 'rgba(255, 255, 255, 0.04)', clickToContextColor: 'rgba(0, 0, 0, 0.05)',
// clickToContextColor: 'rgba(255, 255, 255, 0.08)', brandColor: 'rgba(0, 0, 0, 0.9)'
// color: '#f8f9fa', }
// brandColor: 'var(--primary) !important'
// }
const darkTheme = { const darkTheme = {
body: '#000000', body: '#000000',
@ -88,6 +86,16 @@ const darkTheme = {
brandColor: 'var(--primary) !important' brandColor: 'var(--primary) !important'
} }
function ThemeProviderWrapper ({ children }) {
const me = useMe()
console.log(me)
return (
<ThemeProvider theme={me?.theme === 'light' ? lightTheme : darkTheme}>
{children}
</ThemeProvider>
)
}
function MyApp ({ Component, pageProps: { session, ...props } }) { function MyApp ({ Component, pageProps: { session, ...props } }) {
const client = getApolloClient() const client = getApolloClient()
/* /*
@ -107,11 +115,11 @@ function MyApp ({ Component, pageProps: { session, ...props } }) {
return ( return (
<PlausibleProvider domain='stacker.news' trackOutboundLinks> <PlausibleProvider domain='stacker.news' trackOutboundLinks>
<ThemeProvider theme={darkTheme}> <Provider session={session}>
<GlobalStyle /> <ApolloProvider client={client}>
<Provider session={session}> <MeProvider>
<ApolloProvider client={client}> <ThemeProviderWrapper>
<MeProvider> <GlobalStyle />
<LightningProvider> <LightningProvider>
<FundErrorProvider> <FundErrorProvider>
<FundErrorModal /> <FundErrorModal />
@ -121,10 +129,10 @@ function MyApp ({ Component, pageProps: { session, ...props } }) {
</ItemActProvider> </ItemActProvider>
</FundErrorProvider> </FundErrorProvider>
</LightningProvider> </LightningProvider>
</MeProvider> </ThemeProviderWrapper>
</ApolloProvider> </MeProvider>
</Provider> </ApolloProvider>
</ThemeProvider> </Provider>
</PlausibleProvider> </PlausibleProvider>
) )
} }

View File

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "users" ADD COLUMN "theme" TEXT NOT NULL DEFAULT E'light';

View File

@ -35,6 +35,7 @@ model User {
checkedNotesAt DateTime? checkedNotesAt DateTime?
tipDefault Int @default(0) tipDefault Int @default(0)
pubkey String? @unique pubkey String? @unique
theme String @default("light")
@@index([createdAt]) @@index([createdAt])
@@map(name: "users") @@map(name: "users")

View File

@ -95,6 +95,10 @@ footer {
fill: #6c757d; fill: #6c757d;
} }
.pointer {
cursor: pointer;
}
@media screen and (max-width: 767px) { @media screen and (max-width: 767px) {
input, select, textarea, .form-control, .form-control:focus, .input-group-text { input, select, textarea, .form-control, .form-control:focus, .input-group-text {
font-size: 1rem !important; font-size: 1rem !important;