about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/golang-test-lint.yml8
-rw-r--r--Dockerfile.embedr1
-rw-r--r--assets/kawaii.pngbin0 -> 118701 bytes
-rw-r--r--assets/kawaii_smol.pngbin0 -> 6715 bytes
-rw-r--r--bskyweb/.gitignore2
-rw-r--r--bskyweb/cmd/bskyweb/server.go2
-rw-r--r--bskyweb/static/media/.gitkeep0
-rw-r--r--package.json2
-rw-r--r--src/state/persisted/index.ts8
-rw-r--r--src/state/persisted/schema.ts2
-rw-r--r--src/state/preferences/index.tsx5
-rw-r--r--src/state/preferences/kawaii.tsx50
-rw-r--r--src/view/com/auth/SplashScreen.web.tsx13
-rw-r--r--src/view/com/home/HomeHeaderLayout.web.tsx14
-rw-r--r--src/view/icons/Logo.tsx25
-rw-r--r--src/view/shell/Drawer.tsx13
-rw-r--r--src/view/shell/desktop/RightNav.tsx33
17 files changed, 150 insertions, 28 deletions
diff --git a/.github/workflows/golang-test-lint.yml b/.github/workflows/golang-test-lint.yml
index 2576c3479..a87e7f144 100644
--- a/.github/workflows/golang-test-lint.yml
+++ b/.github/workflows/golang-test-lint.yml
@@ -20,8 +20,8 @@ jobs:
         uses: actions/setup-go@v3
         with:
           go-version: '1.21'
-      - name: Dummy JS File
-        run: touch bskyweb/static/js/blah.js
+      - name: Dummy Static Files
+        run: touch bskyweb/static/js/blah.js && touch bskyweb/static/media/blah.txt
       - name: Check
         run: cd bskyweb/ && make check
       - name: Build (binary)
@@ -37,7 +37,7 @@ jobs:
         uses: actions/setup-go@v3
         with:
           go-version: '1.21'
-      - name: Dummy JS File
-        run: touch bskyweb/static/js/blah.js
+      - name: Dummy Static Files
+        run: touch bskyweb/static/js/blah.js && touch bskyweb/static/media/blah.txt
       - name: Lint
         run: cd bskyweb/ &&  make lint
diff --git a/Dockerfile.embedr b/Dockerfile.embedr
index c70251658..63f060980 100644
--- a/Dockerfile.embedr
+++ b/Dockerfile.embedr
@@ -40,6 +40,7 @@ RUN find ./bskyweb/embedr-static && find ./bskyweb/embedr-templates && find ./bs
 
 # hack around issue with empty directory and go:embed
 RUN touch bskyweb/static/js/empty.txt
+RUN touch bskyweb/static/media/empty.txt
 
 #
 # Generate the embedr Go binary.
diff --git a/assets/kawaii.png b/assets/kawaii.png
new file mode 100644
index 000000000..79cab8e52
--- /dev/null
+++ b/assets/kawaii.png
Binary files differdiff --git a/assets/kawaii_smol.png b/assets/kawaii_smol.png
new file mode 100644
index 000000000..4bed56208
--- /dev/null
+++ b/assets/kawaii_smol.png
Binary files differdiff --git a/bskyweb/.gitignore b/bskyweb/.gitignore
index fad122a28..05b3ad7ab 100644
--- a/bskyweb/.gitignore
+++ b/bskyweb/.gitignore
@@ -10,6 +10,8 @@ static/js/*.js
 static/js/*.map
 static/js/*.js.LICENSE.txt
 static/js/empty.txt
+static/media/*.png
+static/media/empty.txt
 templates/scripts.html
 templates/*-embed.html
 static/embed/*.html
diff --git a/bskyweb/cmd/bskyweb/server.go b/bskyweb/cmd/bskyweb/server.go
index 54580d643..e1b009646 100644
--- a/bskyweb/cmd/bskyweb/server.go
+++ b/bskyweb/cmd/bskyweb/server.go
@@ -158,7 +158,7 @@ func serve(cctx *cli.Context) error {
 
 			// Cache javascript and images files for 1 week, which works because
 			// they're always versioned (e.g. /static/js/main.64c14927.js)
-			if strings.HasPrefix(path, "/static/js/") || strings.HasPrefix(path, "/static/images/") {
+			if strings.HasPrefix(path, "/static/js/") || strings.HasPrefix(path, "/static/images/") || strings.HasPrefix(path, "/static/media/") {
 				maxAge = 7 * (60 * 60 * 24) // 1 week
 			}
 
diff --git a/bskyweb/static/media/.gitkeep b/bskyweb/static/media/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/bskyweb/static/media/.gitkeep
diff --git a/package.json b/package.json
index acb9007b4..874a55c16 100644
--- a/package.json
+++ b/package.json
@@ -15,7 +15,7 @@
     "web": "expo start --web",
     "use-build-number": "./scripts/useBuildNumberEnv.sh",
     "use-build-number-with-bump": "./scripts/useBuildNumberEnvWithBump.sh",
-    "build-web": "expo export:web && node ./scripts/post-web-build.js && cp -v ./web-build/static/js/*.* ./bskyweb/static/js/",
+    "build-web": "expo export:web && node ./scripts/post-web-build.js && cp -v ./web-build/static/js/*.* ./bskyweb/static/js/ && cp -v ./web-build/static/media/*.png ./bskyweb/static/media/",
     "build-all": "yarn intl:build && yarn use-build-number-with-bump eas build --platform all",
     "build-ios": "yarn use-build-number-with-bump eas build -p ios",
     "build-android": "yarn use-build-number-with-bump eas build -p android",
diff --git a/src/state/persisted/index.ts b/src/state/persisted/index.ts
index f57172d2f..5fe0f9bd0 100644
--- a/src/state/persisted/index.ts
+++ b/src/state/persisted/index.ts
@@ -1,11 +1,11 @@
 import EventEmitter from 'eventemitter3'
+
+import BroadcastChannel from '#/lib/broadcast'
 import {logger} from '#/logger'
-import {defaults, Schema} from '#/state/persisted/schema'
 import {migrate} from '#/state/persisted/legacy'
+import {defaults, Schema} from '#/state/persisted/schema'
 import * as store from '#/state/persisted/store'
-import BroadcastChannel from '#/lib/broadcast'
-
-export type {Schema, PersistedAccount} from '#/state/persisted/schema'
+export type {PersistedAccount, Schema} from '#/state/persisted/schema'
 export {defaults} from '#/state/persisted/schema'
 
 const broadcast = new BroadcastChannel('BSKY_BROADCAST_CHANNEL')
diff --git a/src/state/persisted/schema.ts b/src/state/persisted/schema.ts
index 43f08e12e..77a79b78e 100644
--- a/src/state/persisted/schema.ts
+++ b/src/state/persisted/schema.ts
@@ -80,6 +80,7 @@ export const schema = z.object({
   pdsAddressHistory: z.array(z.string()).optional(),
   disableHaptics: z.boolean().optional(),
   disableAutoplay: z.boolean().optional(),
+  kawaii: z.boolean().optional(),
 })
 export type Schema = z.infer<typeof schema>
 
@@ -117,4 +118,5 @@ export const defaults: Schema = {
   pdsAddressHistory: [],
   disableHaptics: false,
   disableAutoplay: prefersReducedMotion,
+  kawaii: false,
 }
diff --git a/src/state/preferences/index.tsx b/src/state/preferences/index.tsx
index 820358518..5bca35452 100644
--- a/src/state/preferences/index.tsx
+++ b/src/state/preferences/index.tsx
@@ -7,6 +7,7 @@ import {Provider as DisableHapticsProvider} from './disable-haptics'
 import {Provider as ExternalEmbedsProvider} from './external-embeds-prefs'
 import {Provider as HiddenPostsProvider} from './hidden-posts'
 import {Provider as InAppBrowserProvider} from './in-app-browser'
+import {Provider as KawaiiProvider} from './kawaii'
 import {Provider as LanguagesProvider} from './languages'
 
 export {
@@ -32,7 +33,9 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
             <InAppBrowserProvider>
               <DisableHapticsProvider>
                 <AutoplayProvider>
-                  <DmServiceUrlProvider>{children}</DmServiceUrlProvider>
+                  <DmServiceUrlProvider>
+                    <KawaiiProvider>{children}</KawaiiProvider>
+                  </DmServiceUrlProvider>
                 </AutoplayProvider>
               </DisableHapticsProvider>
             </InAppBrowserProvider>
diff --git a/src/state/preferences/kawaii.tsx b/src/state/preferences/kawaii.tsx
new file mode 100644
index 000000000..4aa95ef8b
--- /dev/null
+++ b/src/state/preferences/kawaii.tsx
@@ -0,0 +1,50 @@
+import React from 'react'
+
+import {isWeb} from '#/platform/detection'
+import * as persisted from '#/state/persisted'
+
+type StateContext = persisted.Schema['kawaii']
+
+const stateContext = React.createContext<StateContext>(
+  persisted.defaults.kawaii,
+)
+
+export function Provider({children}: React.PropsWithChildren<{}>) {
+  const [state, setState] = React.useState(persisted.get('kawaii'))
+
+  const setStateWrapped = React.useCallback(
+    (kawaii: persisted.Schema['kawaii']) => {
+      setState(kawaii)
+      persisted.write('kawaii', kawaii)
+    },
+    [setState],
+  )
+
+  React.useEffect(() => {
+    return persisted.onUpdate(() => {
+      setState(persisted.get('kawaii'))
+    })
+  }, [setStateWrapped])
+
+  React.useEffect(() => {
+    // dumb and stupid but it's web only so just refresh the page if you want to change it
+
+    if (isWeb) {
+      const kawaii = new URLSearchParams(window.location.search).get('kawaii')
+      switch (kawaii) {
+        case 'true':
+          setStateWrapped(true)
+          break
+        case 'false':
+          setStateWrapped(false)
+          break
+      }
+    }
+  }, [setStateWrapped])
+
+  return <stateContext.Provider value={state}>{children}</stateContext.Provider>
+}
+
+export function useKawaiiMode() {
+  return React.useContext(stateContext)
+}
diff --git a/src/view/com/auth/SplashScreen.web.tsx b/src/view/com/auth/SplashScreen.web.tsx
index f905e1e8d..6df4e439a 100644
--- a/src/view/com/auth/SplashScreen.web.tsx
+++ b/src/view/com/auth/SplashScreen.web.tsx
@@ -4,6 +4,7 @@ import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
 import {msg, Trans} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
 
+import {useKawaiiMode} from '#/state/preferences/kawaii'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
 import {Logo} from '#/view/icons/Logo'
 import {Logotype} from '#/view/icons/Logotype'
@@ -28,6 +29,8 @@ export const SplashScreen = ({
   const t = useTheme()
   const {isTabletOrMobile: isMobileWeb} = useWebMediaQueries()
 
+  const kawaii = useKawaiiMode()
+
   return (
     <>
       {onDismiss && (
@@ -66,11 +69,13 @@ export const SplashScreen = ({
           ]}>
           <ErrorBoundary>
             <View style={[a.justify_center, a.align_center]}>
-              <Logo width={92} fill="sky" />
+              <Logo width={kawaii ? 300 : 92} fill="sky" />
 
-              <View style={[a.pb_sm, a.pt_5xl]}>
-                <Logotype width={161} fill={t.atoms.text.color} />
-              </View>
+              {!kawaii && (
+                <View style={[a.pb_sm, a.pt_5xl]}>
+                  <Logotype width={161} fill={t.atoms.text.color} />
+                </View>
+              )}
 
               <Text
                 style={[
diff --git a/src/view/com/home/HomeHeaderLayout.web.tsx b/src/view/com/home/HomeHeaderLayout.web.tsx
index 644d4cab6..f00a15b3f 100644
--- a/src/view/com/home/HomeHeaderLayout.web.tsx
+++ b/src/view/com/home/HomeHeaderLayout.web.tsx
@@ -15,6 +15,7 @@ import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode'
 import {usePalette} from 'lib/hooks/usePalette'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
 import {Logo} from '#/view/icons/Logo'
+import {useKawaiiMode} from '../../../state/preferences/kawaii'
 import {Link} from '../util/Link'
 import {HomeHeaderLayoutMobile} from './HomeHeaderLayoutMobile'
 
@@ -43,10 +44,19 @@ function HomeHeaderLayoutDesktopAndTablet({
   const {hasSession} = useSession()
   const {_} = useLingui()
 
+  const kawaii = useKawaiiMode()
+
   return (
     <>
       {hasSession && (
-        <View style={[pal.view, pal.border, styles.bar, styles.topBar]}>
+        <View
+          style={[
+            pal.view,
+            pal.border,
+            styles.bar,
+            styles.topBar,
+            kawaii && {paddingTop: 4, paddingBottom: 0},
+          ]}>
           <Link
             href="/settings/following-feed"
             hitSlop={10}
@@ -58,7 +68,7 @@ function HomeHeaderLayoutDesktopAndTablet({
               style={pal.textLight as FontAwesomeIconStyle}
             />
           </Link>
-          <Logo width={28} />
+          <Logo width={kawaii ? 60 : 28} />
           <Link
             href="/settings/saved-feeds"
             hitSlop={10}
diff --git a/src/view/icons/Logo.tsx b/src/view/icons/Logo.tsx
index 9212381a9..4de7c1613 100644
--- a/src/view/icons/Logo.tsx
+++ b/src/view/icons/Logo.tsx
@@ -1,15 +1,17 @@
 import React from 'react'
 import {StyleSheet, TextProps} from 'react-native'
 import Svg, {
-  Path,
   Defs,
   LinearGradient,
+  Path,
+  PathProps,
   Stop,
   SvgProps,
-  PathProps,
 } from 'react-native-svg'
+import {Image} from 'expo-image'
 
 import {colors} from '#/lib/styles'
+import {useKawaiiMode} from '#/state/preferences/kawaii'
 
 const ratio = 57 / 64
 
@@ -25,6 +27,25 @@ export const Logo = React.forwardRef(function LogoImpl(props: Props, ref) {
   const _fill = gradient ? 'url(#sky)' : fill || styles?.color || colors.blue3
   // @ts-ignore it's fiiiiine
   const size = parseInt(rest.width || 32)
+
+  const isKawaii = useKawaiiMode()
+
+  if (isKawaii) {
+    return (
+      <Image
+        source={
+          size > 100
+            ? require('../../../assets/kawaii.png')
+            : require('../../../assets/kawaii_smol.png')
+        }
+        accessibilityLabel="Bluesky"
+        accessibilityHint=""
+        accessibilityIgnoresInvertColors
+        style={[{height: size, aspectRatio: 1.4}]}
+      />
+    )
+  }
+
   return (
     <Svg
       fill="none"
diff --git a/src/view/shell/Drawer.tsx b/src/view/shell/Drawer.tsx
index 8145fa408..d8e604ec3 100644
--- a/src/view/shell/Drawer.tsx
+++ b/src/view/shell/Drawer.tsx
@@ -18,6 +18,7 @@ import {useLingui} from '@lingui/react'
 import {StackActions, useNavigation} from '@react-navigation/native'
 
 import {emitSoftReset} from '#/state/events'
+import {useKawaiiMode} from '#/state/preferences/kawaii'
 import {useUnreadNotifications} from '#/state/queries/notifications/unread'
 import {useProfileQuery} from '#/state/queries/profile'
 import {SessionAccount, useSession} from '#/state/session'
@@ -117,6 +118,7 @@ let DrawerContent = ({}: {}): React.ReactNode => {
   const {isAtHome, isAtSearch, isAtFeeds, isAtNotifications, isAtMyProfile} =
     useNavigationTabState()
   const {hasSession, currentAccount} = useSession()
+  const kawaii = useKawaiiMode()
 
   // events
   // =
@@ -262,6 +264,17 @@ let DrawerContent = ({}: {}): React.ReactNode => {
               href="https://bsky.social/about/support/privacy-policy"
               text={_(msg`Privacy Policy`)}
             />
+            {kawaii && (
+              <Text type="md" style={pal.textLight}>
+                Logo by{' '}
+                <TextLink
+                  type="md"
+                  href="/profile/sawaratsuki.bsky.social"
+                  text="@sawaratsuki.bsky.social"
+                  style={pal.link}
+                />
+              </Text>
+            )}
           </View>
 
           <View style={styles.smallSpacer} />
diff --git a/src/view/shell/desktop/RightNav.tsx b/src/view/shell/desktop/RightNav.tsx
index c1f498724..f0cd4f59a 100644
--- a/src/view/shell/desktop/RightNav.tsx
+++ b/src/view/shell/desktop/RightNav.tsx
@@ -1,22 +1,26 @@
 import React from 'react'
 import {StyleSheet, View} from 'react-native'
-import {usePalette} from 'lib/hooks/usePalette'
-import {DesktopSearch} from './Search'
-import {DesktopFeeds} from './Feeds'
-import {Text} from 'view/com/util/text/Text'
-import {TextLink} from 'view/com/util/Link'
-import {FEEDBACK_FORM_URL, HELP_DESK_URL} from 'lib/constants'
-import {s} from 'lib/styles'
-import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
-import {useLingui} from '@lingui/react'
 import {msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+
+import {useKawaiiMode} from '#/state/preferences/kawaii'
 import {useSession} from '#/state/session'
+import {FEEDBACK_FORM_URL, HELP_DESK_URL} from 'lib/constants'
+import {usePalette} from 'lib/hooks/usePalette'
+import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
+import {s} from 'lib/styles'
+import {TextLink} from 'view/com/util/Link'
+import {Text} from 'view/com/util/text/Text'
+import {DesktopFeeds} from './Feeds'
+import {DesktopSearch} from './Search'
 
 export function DesktopRightNav({routeName}: {routeName: string}) {
   const pal = usePalette('default')
   const {_} = useLingui()
   const {hasSession, currentAccount} = useSession()
 
+  const kawaii = useKawaiiMode()
+
   const {isTablet} = useWebMediaQueries()
   if (isTablet) {
     return null
@@ -90,6 +94,17 @@ export function DesktopRightNav({routeName}: {routeName: string}) {
               text={_(msg`Help`)}
             />
           </View>
+          {kawaii && (
+            <Text type="md" style={[pal.textLight, {marginTop: 12}]}>
+              Logo by{' '}
+              <TextLink
+                type="md"
+                href="/profile/sawaratsuki.bsky.social"
+                text="@sawaratsuki.bsky.social"
+                style={pal.link}
+              />
+            </Text>
+          )}
         </View>
       </View>
     </View>