Mirror — see github.com/blacksky-algorithms/blacksky.community
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

Restore Blacksky branding and theming after upstream merge

Restore the pre-merge color scheme and theming system that was
overwritten during the upstream social-app merge. The upstream merge
replaced our custom createThemes() with the @bsky.app/alf package
version and stripped CSS variables from style.css.

Theming:
- Restore custom createThemes() in themes.ts with BRAND constants
(indigo #6060E9, lime #D2FC51, twilight #161E27, etc.)
- Restore colorGeneration.ts with HSL-based dim palette generation
- Restore CSS variables and theme--light/dark/dim classes in style.css
- Restore ProseMirror mention color to rgb(96, 96, 233)

HTML templates:
- Restore pre-merge flash-prevention CSS (simple background/color
with prefers-color-scheme media query, no inline CSS variables)
- Restore Blacksky SVG splash with currentColor fill and
transform-based centering
- Update preconnect to blacksky.community/go.blacksky.community
- Set mask-icon and theme-color to #6060E9

Branding:
- Change tagline to "Join the Cookout" in NavSignupCard
- Blacksky logo, splash screens, and footer links
- Update @atproto/api patch for v0.18.18
- Replace bsky.social references with blackskyweb.xyz
- Default avatar color #6060E9
- Blacksky constants (endpoints, feeds, DIDs)

+976 -295
+40 -66
bskyweb/templates/base.html
··· 7 7 <!-- 8 8 Preconnect to essential domains 9 9 --> 10 - <link rel="preconnect" href="https://bsky.social"> 11 - <link rel="preconnect" href="https://go.bsky.app"> 12 - <title>{%- block head_title -%}Bluesky{%- endblock -%}</title> 10 + <link rel="preconnect" href="https://blacksky.community"> 11 + <link rel="preconnect" href="https://go.blacksky.community"> 12 + <title>{%- block head_title -%}Blacksky{%- endblock -%}</title> 13 13 14 14 <!-- Hello Humans! API docs at https://atproto.com --> 15 15 ··· 37 37 font-style: italic; 38 38 font-display: swap; 39 39 } 40 + html { 41 + background-color: #F8FAF9; 42 + color: #000000; 43 + } 44 + @media (prefers-color-scheme: dark) { 45 + html { 46 + background-color: #070C0C; 47 + color: #FFFFFF; 48 + } 49 + } 40 50 html, 41 51 body { 42 52 margin: 0px; ··· 51 61 -ms-overflow-style: scrollbar; 52 62 font-synthesis-weight: none; 53 63 } 54 - :root { 55 - --text: black; 56 - --background: white; 57 - --backgroundLight: #e2e7ee; 58 - } 59 - @media (prefers-color-scheme: dark) { 60 - :root { 61 - color-scheme: dark; 62 - --text: white; 63 - --background: black; 64 - --backgroundLight: #232e3e; 65 - } 66 - } 67 64 html, 68 65 body, 69 66 #root { ··· 72 69 min-height: 100%; 73 70 width: 100%; 74 71 } 75 - html.theme--light, 76 - html.theme--light body, 77 - html.theme--light #root { 78 - background-color: white; 79 - --text: black; 80 - --background: white; 81 - --backgroundLight: #DCE2EA; 82 - } 83 - html.theme--dark, 84 - html.theme--dark body, 85 - html.theme--dark #root { 86 - color-scheme: dark; 87 - background-color: black; 88 - --text: white; 89 - --background: black; 90 - --backgroundLight: #232E3E; 91 - } 92 - html.theme--dim, 93 - html.theme--dim body, 94 - html.theme--dim #root { 95 - color-scheme: dark; 96 - background-color: #151D28; 97 - --text: white; 98 - --background: #151D28; 99 - --backgroundLight: #2C3A4E; 100 - } 101 72 #splash { 102 - display: flex; 103 73 position: fixed; 104 - top: 0; 105 - bottom: 0; 106 - left: 0; 107 - right: 0; 108 - align-items: center; 109 - justify-content: center; 110 - } 111 - #splash svg { 112 - position: relative; 113 - top: -50px; 114 74 width: 100px; 75 + left: 50%; 76 + top: 50%; 77 + transform: translateX(-50%) translateY(-50%) translateY(-50px); 115 78 } 116 79 /** 117 80 * We need these styles to prevent shifting due to scrollbar show/hide on ··· 124 87 overflow-y: scroll; 125 88 } 126 89 </style> 127 - <script> 128 - const theme = localStorage.getItem('ALF_THEME') 129 - if (theme) { 130 - document.documentElement.classList.add(`theme--${theme}`) 131 - } 132 - </script> 133 90 134 91 {% include "scripts.html" %} 135 92 <link rel="apple-touch-icon" sizes="180x180" href="{{ staticCDNHost }}/static/apple-touch-icon.png"> 136 93 <link rel="icon" type="image/png" sizes="32x32" href="{{ staticCDNHost }}/static/favicon-32x32.png"> 137 94 <link rel="icon" type="image/png" sizes="16x16" href="{{ staticCDNHost }}/static/favicon-16x16.png"> 138 - <link rel="mask-icon" href="{{ staticCDNHost }}/static/safari-pinned-tab.svg" color="#1185fe"> 95 + <link rel="mask-icon" href="{{ staticCDNHost }}/static/safari-pinned-tab.svg" color="#6060E9"> 139 96 <meta name="theme-color"> 140 - <meta name="application-name" content="Bluesky"> 97 + <meta name="application-name" content="Blacksky"> 141 98 <meta name="generator" content="bskyweb"> 142 - <meta property="og:site_name" content="Bluesky Social"> 99 + <meta property="og:site_name" content="Blacksky"> 143 100 <meta property="og:logo" content="{{ favicon }}"> 144 - <meta name="twitter:site" content="@bluesky" /> 101 + <meta name="twitter:site" content="@blacksky" /> 145 102 <link type="application/activity+json" href="" /> 146 103 147 104 {% block html_head_extra -%}{%- endblock %} ··· 150 107 {%- block body_all %} 151 108 <div id="root"> 152 109 <div id="splash"> 153 - <!-- Bluesky SVG --> 154 - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 57"><path fill="#006AFF" d="M13.873 3.805C21.21 9.332 29.103 20.537 32 26.55v15.882c0-.338-.13.044-.41.867-1.512 4.456-7.418 21.847-20.923 7.944-7.111-7.32-3.819-14.64 9.125-16.85-7.405 1.264-15.73-.825-18.014-9.015C1.12 23.022 0 8.51 0 6.55 0-3.268 8.579-.182 13.873 3.805ZM50.127 3.805C42.79 9.332 34.897 20.537 32 26.55v15.882c0-.338.13.044.41.867 1.512 4.456 7.418 21.847 20.923 7.944 7.111-7.32 3.819-14.64-9.125-16.85 7.405 1.264 15.73-.825 18.014-9.015C62.88 23.022 64 8.51 64 6.55c0-9.818-8.578-6.732-13.873-2.745Z"/></svg> 110 + <!-- Blacksky SVG scaled by parent width (100 px) --> 111 + <svg 112 + xmlns="http://www.w3.org/2000/svg" 113 + viewBox="0 0 285 243" 114 + preserveAspectRatio="xMidYMid meet" 115 + style="width:100%;height:auto;display:block" 116 + > 117 + <g clip-path="url(#clip0_1011_989)"> 118 + <path d="M148.846 144.562C148.846 159.75 161.158 172.062 176.346 172.062H207.012V185.865H176.346C161.158 185.865 148.846 198.177 148.846 213.365V243.045H136.029V213.365C136.029 198.177 123.717 185.865 108.529 185.865H77.8633V172.062H108.529C123.717 172.062 136.029 159.75 136.029 144.562V113.896H148.846V144.562Z" fill="currentColor"/> 119 + <path d="M170.946 31.8766C160.207 42.616 160.207 60.0281 170.946 70.7675L192.631 92.4516L182.871 102.212L161.186 80.5275C150.447 69.7881 133.035 69.7881 122.296 80.5275L101.309 101.514L92.2456 92.4509L113.232 71.4642C123.972 60.7248 123.972 43.3128 113.232 32.5733L91.5488 10.8899L101.309 1.12988L122.993 22.814C133.732 33.5533 151.144 33.5534 161.884 22.814L183.568 1.12988L192.631 10.1925L170.946 31.8766Z" fill="currentColor"/> 120 + <path d="M79.0525 75.3259C75.1216 89.9962 83.8276 105.076 98.498 109.006L128.119 116.943L124.547 130.275L94.9267 122.338C80.2564 118.407 65.1772 127.113 61.2463 141.784L53.5643 170.453L41.1837 167.136L48.8654 138.467C52.7963 123.797 44.0902 108.718 29.4199 104.787L-0.201172 96.8497L3.37124 83.5173L32.9923 91.4542C47.6626 95.3851 62.7419 86.679 66.6728 72.0088L74.6098 42.3877L86.9895 45.7048L79.0525 75.3259Z" fill="currentColor"/> 121 + <path d="M218.413 71.4229C222.344 86.093 237.423 94.7992 252.094 90.8683L281.715 82.9313L285.287 96.2628L255.666 104.2C240.995 108.131 232.29 123.21 236.22 137.88L243.902 166.55L231.522 169.867L223.841 141.198C219.91 126.528 204.831 117.822 190.16 121.753L160.539 129.69L156.967 116.357L186.588 108.42C201.258 104.49 209.964 89.4103 206.033 74.74L198.096 45.1189L210.476 41.8018L218.413 71.4229Z" fill="currentColor"/> 122 + </g> 123 + <defs> 124 + <clipPath id="clip0_1011_989"> 125 + <rect width="285" height="243" fill="white"/> 126 + </clipPath> 127 + </defs> 128 + </svg> 155 129 </div> 156 130 </div> 157 131 158 132 <noscript> 159 133 <h1 lang="en">JavaScript Required</h1> 160 134 <p lang="en">This is a heavily interactive web application, and JavaScript is required. Simple HTML interfaces are possible, but that is not what this is. 161 - <p lang="en">Learn more about Bluesky at <a href="https://bsky.social">bsky.social</a> and <a href="https://atproto.com">atproto.com</a>. 135 + <p lang="en">Learn more about Blacksky at <a href="https://blackskyweb.xyz">blackskyweb.xyz</a> and <a href="https://atproto.com">atproto.com</a>, or this fork at <a href="https://github.com/blacksky-algorithms/blacksky.community">github.com/blacksky-algorithms/blacksky.community</a>.</p> 162 136 {% block noscript_extra %}{% endblock %} 163 137 </noscript> 164 138 {% endblock -%}
+3 -3
bskyweb/templates/feed.html
··· 2 2 3 3 {% block head_title %} 4 4 {%- if feedView -%} 5 - {{ feedView.DisplayName }} by @{{ feedView.Creator.Handle }} | Bluesky Feed 5 + {{ feedView.DisplayName }} by @{{ feedView.Creator.Handle }} | Blacksky Feed 6 6 {%- else -%} 7 - Bluesky 7 + Blacksky 8 8 {%- endif -%} 9 9 {% endblock %} 10 10 11 11 {% block html_head_extra -%} 12 12 {%- if feedView -%} 13 - <meta property="og:site_name" content="Bluesky Social"> 13 + <meta property="og:site_name" content="Blacksky"> 14 14 <meta property="og:type" content="website"> 15 15 {%- if requestURI %} 16 16 <meta property="og:url" content="{{ requestURI }}">
+3 -3
bskyweb/templates/post.html
··· 2 2 3 3 {% block head_title %} 4 4 {%- if postView -%} 5 - @{{ postView.Author.Handle }} on Bluesky 5 + @{{ postView.Author.Handle }} on Blacksky 6 6 {%- elif requiresAuth and profileHandle -%} 7 - @{{ profileHandle }} on Bluesky 7 + @{{ profileHandle }} on Blacksky 8 8 {%- else -%} 9 - Bluesky 9 + Blacksky 10 10 {%- endif -%} 11 11 {% endblock %} 12 12
+3 -3
bskyweb/templates/profile.html
··· 2 2 3 3 {% block head_title %} 4 4 {%- if profileView -%} 5 - @{{ profileView.Handle }} on Bluesky 5 + @{{ profileView.Handle }} on Blacksky 6 6 {%- else -%} 7 - Bluesky 7 + Blacksky 8 8 {%- endif -%} 9 9 {% endblock %} 10 10 11 11 {% block html_head_extra -%} 12 - <meta property="og:site_name" content="Bluesky Social"> 12 + <meta property="og:site_name" content="Blacksky"> 13 13 <meta property="og:type" content="profile"> 14 14 {%- if requestURI %} 15 15 <meta property="og:url" content="{{ requestURI }}">
+2 -2
bskyweb/templates/starterpack.html
··· 17 17 <meta property="og:title" content="{{ title }}" /> 18 18 <meta name="twitter:title" content="{{ title }}" /> 19 19 {%- else -%} 20 - <meta property="og:title" content="Bluesky" /> 21 - <meta name="twitter:title" content="Bluesky" /> 20 + <meta property="og:title" content="Blacksky" /> 21 + <meta name="twitter:title" content="Blacksky" /> 22 22 {% endif -%} 23 23 <meta name="description" content="Join the cookout" /> 24 24 <meta name="og:description" content="Join the cookout" />
+4 -4
patches/@atproto+api+0.16.7.patch patches/@atproto+api+0.18.18.patch
··· 1 1 diff --git a/node_modules/@atproto/api/dist/agent.js b/node_modules/@atproto/api/dist/agent.js 2 - index 8d2744e..dc9f39b 100644 2 + index 634e463..57b5c74 100644 3 3 --- a/node_modules/@atproto/api/dist/agent.js 4 4 +++ b/node_modules/@atproto/api/dist/agent.js 5 - @@ -590,7 +590,7 @@ class Agent extends xrpc_1.XrpcClient { 6 - hideBadges: false, 5 + @@ -593,7 +593,7 @@ class Agent extends xrpc_1.XrpcClient { 6 + hideAllFeeds: false, 7 7 }, 8 8 }; 9 9 - const res = await this.app.bsky.actor.getPreferences({}); ··· 11 11 const labelPrefs = []; 12 12 for (const pref of res.data.preferences) { 13 13 if (predicate.isValidAdultContentPref(pref)) { 14 - @@ -1237,14 +1237,14 @@ class Agent extends xrpc_1.XrpcClient { 14 + @@ -1275,14 +1275,14 @@ class Agent extends xrpc_1.XrpcClient { 15 15 async updatePreferences(cb) { 16 16 try { 17 17 await __classPrivateFieldGet(this, _Agent_prefsLock, "f").acquireAsync();
+23 -2
src/App.web.tsx
··· 33 33 useSession, 34 34 useSessionApi, 35 35 } from '#/state/session' 36 + import {getWebOAuthClient} from '#/state/session/oauth-web-client' 36 37 import {readLastActiveAccount} from '#/state/session/util' 37 38 import {Provider as ShellStateProvider} from '#/state/shell' 38 39 import {Provider as ComposerProvider} from '#/state/shell/composer' ··· 92 93 function InnerApp() { 93 94 const [isReady, setIsReady] = React.useState(false) 94 95 const {currentAccount} = useSession() 95 - const {resumeSession} = useSessionApi() 96 + const {resumeSession, login} = useSessionApi() 96 97 const theme = useColorModeTheme() 97 98 const {_} = useLingui() 98 99 const hasCheckedReferrer = useStarterPackEntry() ··· 101 102 useEffect(() => { 102 103 async function onLaunch(account?: SessionAccount) { 103 104 try { 105 + // Check for OAuth callback params first (loopback redirects to /) 106 + if (hasOAuthCallbackParams()) { 107 + const client = getWebOAuthClient() 108 + const result = await client.init() 109 + if (result?.session) { 110 + await login( 111 + { 112 + service: '', 113 + identifier: '', 114 + password: '', 115 + oauthSession: result.session, 116 + }, 117 + 'LoginForm', 118 + ) 119 + // Clear hash fragment after processing 120 + window.history.replaceState(null, '', window.location.pathname) 121 + return 122 + } 123 + } 124 + 104 125 if (account) { 105 126 await resumeSession(account) 106 127 } else { ··· 114 135 } 115 136 const account = readLastActiveAccount() 116 137 onLaunch(account) 117 - }, [resumeSession]) 138 + }, [resumeSession, login]) 118 139 119 140 useEffect(() => { 120 141 return listenSessionDropped(() => {
+33 -7
src/Splash.tsx
··· 15 15 withTiming, 16 16 } from 'react-native-reanimated' 17 17 import {useSafeAreaInsets} from 'react-native-safe-area-context' 18 - import Svg, {Path, type SvgProps} from 'react-native-svg' 18 + import Svg, { 19 + ClipPath, 20 + Defs, 21 + G, 22 + Path, 23 + Rect, 24 + type SvgProps, 25 + } from 'react-native-svg' 19 26 import {Image} from 'expo-image' 20 27 import * as SplashScreen from 'expo-splash-screen' 21 28 ··· 31 38 32 39 export const Logo = React.forwardRef(function LogoImpl(props: SvgProps, ref) { 33 40 const width = 1000 34 - const height = width * (67 / 64) 41 + const height = width * (243 / 285) 35 42 return ( 36 43 <Svg 37 44 fill="none" 38 45 // @ts-ignore it's fiiiiine 39 46 ref={ref} 40 - viewBox="0 0 64 66" 47 + viewBox="0 0 285 243" 41 48 style={[{width, height}, props.style]}> 42 - <Path 43 - fill={props.fill || '#fff'} 44 - d="M13.873 3.77C21.21 9.243 29.103 20.342 32 26.3v15.732c0-.335-.13.043-.41.858-1.512 4.414-7.418 21.642-20.923 7.87-7.111-7.252-3.819-14.503 9.125-16.692-7.405 1.252-15.73-.817-18.014-8.93C1.12 22.804 0 8.431 0 6.488 0-3.237 8.579-.18 13.873 3.77ZM50.127 3.77C42.79 9.243 34.897 20.342 32 26.3v15.732c0-.335.13.043.41.858 1.512 4.414 7.418 21.642 20.923 7.87 7.111-7.252 3.819-14.503-9.125-16.692 7.405 1.252 15.73-.817 18.014-8.93C62.88 22.804 64 8.431 64 6.488 64-3.237 55.422-.18 50.127 3.77Z" 45 - /> 49 + <G clipPath="url(#clip0_splash)"> 50 + <Path 51 + fill={props.fill || '#fff'} 52 + d="M148.846 144.562C148.846 159.75 161.158 172.062 176.346 172.062H207.012V185.865H176.346C161.158 185.865 148.846 198.177 148.846 213.365V243.045H136.029V213.365C136.029 198.177 123.717 185.865 108.529 185.865H77.8633V172.062H108.529C123.717 172.062 136.029 159.75 136.029 144.562V113.896H148.846V144.562Z" 53 + /> 54 + <Path 55 + fill={props.fill || '#fff'} 56 + d="M170.946 31.8766C160.207 42.616 160.207 60.0281 170.946 70.7675L192.631 92.4516L182.871 102.212L161.186 80.5275C150.447 69.7881 133.035 69.7881 122.296 80.5275L101.309 101.514L92.2456 92.4509L113.232 71.4642C123.972 60.7248 123.972 43.3128 113.232 32.5733L91.5488 10.8899L101.309 1.12988L122.993 22.814C133.732 33.5533 151.144 33.5534 161.884 22.814L183.568 1.12988L192.631 10.1925L170.946 31.8766Z" 57 + /> 58 + <Path 59 + fill={props.fill || '#fff'} 60 + d="M79.0525 75.3259C75.1216 89.9962 83.8276 105.076 98.498 109.006L128.119 116.943L124.547 130.275L94.9267 122.338C80.2564 118.407 65.1772 127.113 61.2463 141.784L53.5643 170.453L41.1837 167.136L48.8654 138.467C52.7963 123.797 44.0902 108.718 29.4199 104.787L-0.201172 96.8497L3.37124 83.5173L32.9923 91.4542C47.6626 95.3851 62.7419 86.679 66.6728 72.0088L74.6098 42.3877L86.9895 45.7048L79.0525 75.3259Z" 61 + /> 62 + <Path 63 + fill={props.fill || '#fff'} 64 + d="M218.413 71.4229C222.344 86.093 237.423 94.7992 252.094 90.8683L281.715 82.9313L285.287 96.2628L255.666 104.2C240.995 108.131 232.29 123.21 236.22 137.88L243.902 166.55L231.522 169.867L223.841 141.198C219.91 126.528 204.831 117.822 190.16 121.753L160.539 129.69L156.967 116.357L186.588 108.42C201.258 104.49 209.964 89.4103 206.033 74.74L198.096 45.1189L210.476 41.8018L218.413 71.4229Z" 65 + /> 66 + </G> 67 + <Defs> 68 + <ClipPath id="clip0_splash"> 69 + <Rect width="285" height="243" fill="white" /> 70 + </ClipPath> 71 + </Defs> 46 72 </Svg> 47 73 ) 48 74 })
+26 -7
src/Splash.web.tsx
··· 5 5 */ 6 6 7 7 import {View} from 'react-native' 8 - import Svg, {Path} from 'react-native-svg' 8 + import Svg, {ClipPath, Defs, G, Path, Rect} from 'react-native-svg' 9 9 10 10 import {atoms as a} from '#/alf' 11 11 12 12 const size = 100 13 - const ratio = 57 / 64 13 + const ratio = 243 / 285 14 14 15 15 export function Splash() { 16 16 return ( 17 17 <View style={[a.fixed, a.inset_0, a.align_center, a.justify_center]}> 18 18 <Svg 19 19 fill="none" 20 - viewBox="0 0 64 57" 20 + viewBox="0 0 285 243" 21 21 style={[a.relative, {width: size, height: size * ratio, top: -50}]}> 22 - <Path 23 - fill="#006AFF" 24 - d="M13.873 3.805C21.21 9.332 29.103 20.537 32 26.55v15.882c0-.338-.13.044-.41.867-1.512 4.456-7.418 21.847-20.923 7.944-7.111-7.32-3.819-14.64 9.125-16.85-7.405 1.264-15.73-.825-18.014-9.015C1.12 23.022 0 8.51 0 6.55 0-3.268 8.579-.182 13.873 3.805ZM50.127 3.805C42.79 9.332 34.897 20.537 32 26.55v15.882c0-.338.13.044.41.867 1.512 4.456 7.418 21.847 20.923 7.944 7.111-7.32 3.819-14.64-9.125-16.85 7.405 1.264 15.73-.825 18.014-9.015C62.88 23.022 64 8.51 64 6.55c0-9.818-8.578-6.732-13.873-2.745Z" 25 - /> 22 + <G clipPath="url(#clip0_splash_web)"> 23 + <Path 24 + fill="var(--text)" 25 + d="M148.846 144.562C148.846 159.75 161.158 172.062 176.346 172.062H207.012V185.865H176.346C161.158 185.865 148.846 198.177 148.846 213.365V243.045H136.029V213.365C136.029 198.177 123.717 185.865 108.529 185.865H77.8633V172.062H108.529C123.717 172.062 136.029 159.75 136.029 144.562V113.896H148.846V144.562Z" 26 + /> 27 + <Path 28 + fill="var(--text)" 29 + d="M170.946 31.8766C160.207 42.616 160.207 60.0281 170.946 70.7675L192.631 92.4516L182.871 102.212L161.186 80.5275C150.447 69.7881 133.035 69.7881 122.296 80.5275L101.309 101.514L92.2456 92.4509L113.232 71.4642C123.972 60.7248 123.972 43.3128 113.232 32.5733L91.5488 10.8899L101.309 1.12988L122.993 22.814C133.732 33.5533 151.144 33.5534 161.884 22.814L183.568 1.12988L192.631 10.1925L170.946 31.8766Z" 30 + /> 31 + <Path 32 + fill="var(--text)" 33 + d="M79.0525 75.3259C75.1216 89.9962 83.8276 105.076 98.498 109.006L128.119 116.943L124.547 130.275L94.9267 122.338C80.2564 118.407 65.1772 127.113 61.2463 141.784L53.5643 170.453L41.1837 167.136L48.8654 138.467C52.7963 123.797 44.0902 108.718 29.4199 104.787L-0.201172 96.8497L3.37124 83.5173L32.9923 91.4542C47.6626 95.3851 62.7419 86.679 66.6728 72.0088L74.6098 42.3877L86.9895 45.7048L79.0525 75.3259Z" 34 + /> 35 + <Path 36 + fill="var(--text)" 37 + d="M218.413 71.4229C222.344 86.093 237.423 94.7992 252.094 90.8683L281.715 82.9313L285.287 96.2628L255.666 104.2C240.995 108.131 232.29 123.21 236.22 137.88L243.902 166.55L231.522 169.867L223.841 141.198C219.91 126.528 204.831 117.822 190.16 121.753L160.539 129.69L156.967 116.357L186.588 108.42C201.258 104.49 209.964 89.4103 206.033 74.74L198.096 45.1189L210.476 41.8018L218.413 71.4229Z" 38 + /> 39 + </G> 40 + <Defs> 41 + <ClipPath id="clip0_splash_web"> 42 + <Rect width="285" height="243" fill="white" /> 43 + </ClipPath> 44 + </Defs> 26 45 </Svg> 27 46 </View> 28 47 )
+607 -22
src/alf/themes.ts
··· 1 + import {type Palette, type Theme} from '@bsky.app/alf' 2 + 3 + import {atoms} from '#/alf/atoms' 1 4 import { 2 - createThemes, 3 - DEFAULT_PALETTE, 4 - DEFAULT_SUBDUED_PALETTE, 5 - } from '@bsky.app/alf' 5 + BLUE_HUE, 6 + defaultScale, 7 + dimScale, 8 + GREEN_HUE, 9 + RED_HUE, 10 + } from '#/alf/util/colorGeneration' 11 + 12 + /** ---------------------------------------------------------------- 13 + * Core brand swatches lifted 1-for-1 from the guideline pages. 14 + * (Add or rename here - _never_ inside a palette - to keep ALF's 15 + * public API unchanged.) 16 + * ----------------------------------------------------------------*/ 17 + export const BRAND = { 18 + /* Neutrals */ 19 + black: '#070C0C', 20 + white: '#F8FAF9', 21 + twilight: '#161E27', 22 + gray300: '#C8CAC9', 23 + gray400: '#9C9E9E', 24 + gray600: '#6A6A6A', 25 + 26 + /* Primary / "Indigo-violet" */ 27 + primaryLight: '#6060E9', 28 + primaryLightTint: '#EAEBFC', 29 + primaryDark: '#8686FF', 30 + primaryDarkTint: '#464985', 31 + 32 + /* Accent / Lime-green ("success") */ 33 + secondary: '#D2FC51', 34 + secondaryTint: '#F1FECB', 35 + 36 + /* Negative / Brand red */ 37 + negative: '#F40B42', 38 + } as const 6 39 7 - const DEFAULT_THEMES = createThemes({ 8 - defaultPalette: DEFAULT_PALETTE, 9 - subduedPalette: DEFAULT_SUBDUED_PALETTE, 40 + export const themes = createThemes({ 41 + hues: { 42 + primary: BLUE_HUE, 43 + negative: RED_HUE, 44 + positive: GREEN_HUE, 45 + }, 10 46 }) 11 47 12 - export const themes = { 13 - lightPalette: DEFAULT_THEMES.light.palette, 14 - darkPalette: DEFAULT_THEMES.dark.palette, 15 - dimPalette: DEFAULT_THEMES.dim.palette, 16 - light: DEFAULT_THEMES.light, 17 - dark: DEFAULT_THEMES.dark, 18 - dim: DEFAULT_THEMES.dim, 19 - } 20 - 21 48 /** 22 49 * @deprecated use ALF and access palette from `useTheme()` 23 50 */ 24 - export const lightPalette = DEFAULT_THEMES.light.palette 51 + export const lightPalette = themes.lightPalette 25 52 /** 26 53 * @deprecated use ALF and access palette from `useTheme()` 27 54 */ 28 - export const darkPalette = DEFAULT_THEMES.dark.palette 55 + export const darkPalette = themes.darkPalette 29 56 /** 30 57 * @deprecated use ALF and access palette from `useTheme()` 31 58 */ 32 - export const dimPalette = DEFAULT_THEMES.dim.palette 59 + export const dimPalette = themes.dimPalette 33 60 /** 34 61 * @deprecated use ALF and access theme from `useTheme()` 35 62 */ 36 - export const light = DEFAULT_THEMES.light 63 + export const light = themes.light 37 64 /** 38 65 * @deprecated use ALF and access theme from `useTheme()` 39 66 */ 40 - export const dark = DEFAULT_THEMES.dark 67 + export const dark = themes.dark 41 68 /** 42 69 * @deprecated use ALF and access theme from `useTheme()` 43 70 */ 44 - export const dim = DEFAULT_THEMES.dim 71 + export const dim = themes.dim 72 + 73 + export const defaultTheme = themes.light 74 + 75 + export function createThemes({ 76 + hues, 77 + }: { 78 + hues: { 79 + primary: number 80 + negative: number 81 + positive: number 82 + } 83 + }): { 84 + lightPalette: Palette 85 + darkPalette: Palette 86 + dimPalette: Palette 87 + light: Theme 88 + dark: Theme 89 + dim: Theme 90 + } { 91 + /** 92 + * ---------------------------------------------------------------- 93 + * _All_ runtime-visible tokens are hard-coded to match the guide. 94 + * The keys remain identical, so nothing else breaks. 95 + * ----------------------------------------------------------------*/ 96 + const color = { 97 + like: '#EC4899', 98 + trueBlack: BRAND.black, 99 + 100 + /* ---------- Neutral Scale (white -> black) ---------- */ 101 + gray_0: BRAND.white, 102 + gray_25: '#F2F4F4', 103 + gray_50: '#E8EAEA', 104 + gray_100: '#DFE1E1', 105 + gray_200: BRAND.gray300, // #C8CAC9 106 + gray_300: '#B6B8B8', 107 + gray_400: BRAND.gray400, // #9C9E9E 108 + gray_500: '#818383', 109 + gray_600: BRAND.gray600, // #6A6A6A 110 + gray_700: '#4F5050', 111 + gray_800: '#353636', 112 + gray_900: '#1F2020', 113 + gray_950: '#121313', 114 + gray_975: '#0B0C0C', 115 + gray_1000: BRAND.black, 116 + 117 + /* ---------- Primary (violet) - light palette anchor ---------- */ 118 + primary_25: BRAND.primaryLightTint, 119 + primary_50: '#DCDDFA', 120 + primary_100: '#C6C8F5', 121 + primary_200: '#B0B3F0', 122 + primary_300: '#989CED', 123 + primary_400: '#8286E7', 124 + primary_500: BRAND.primaryLight, 125 + primary_600: '#5252C3', 126 + primary_700: '#4545A8', 127 + primary_800: '#38388D', 128 + primary_900: '#2B2B71', 129 + primary_950: '#1E1E56', 130 + primary_975: '#13133B', 131 + 132 + /* ---------- "Positive / Success" lime scale ---------- */ 133 + green_25: BRAND.secondaryTint, 134 + green_50: '#EAFDD1', 135 + green_100: '#DAFCAB', 136 + green_200: '#C8FC80', 137 + green_300: '#BBFB66', 138 + green_400: '#AEFA59', 139 + green_500: BRAND.secondary, 140 + green_600: '#A0EC46', 141 + green_700: '#82C838', 142 + green_800: '#66942A', 143 + green_900: '#4A601C', 144 + green_950: '#2E3B0E', 145 + green_975: '#181F07', 146 + 147 + /* ---------- Negative / Error (brand red) ---------- */ 148 + red_25: '#FFE5EC', 149 + red_50: '#FFD9E3', 150 + red_100: '#FFC1D1', 151 + red_200: '#FF9AB3', 152 + red_300: '#FF7396', 153 + red_400: '#FF4B78', 154 + red_500: BRAND.negative, // #F40B42 155 + red_600: '#C00A32', 156 + red_700: '#920826', 157 + red_800: '#630619', 158 + red_900: '#35030D', 159 + red_950: '#1B0206', 160 + red_975: '#0E0103', 161 + } as const 162 + 163 + const lightPalette = { 164 + white: BRAND.white, 165 + black: BRAND.black, 166 + like: color.like, 167 + 168 + contrast_0: color.gray_0, 169 + contrast_25: color.gray_25, 170 + contrast_50: color.gray_50, 171 + contrast_100: color.gray_100, 172 + contrast_200: color.gray_200, 173 + contrast_300: color.gray_300, 174 + contrast_400: color.gray_400, 175 + contrast_500: color.gray_500, 176 + contrast_600: color.gray_600, 177 + contrast_700: color.gray_700, 178 + contrast_800: color.gray_800, 179 + contrast_900: color.gray_900, 180 + contrast_950: color.gray_950, 181 + contrast_975: color.gray_975, 182 + contrast_1000: color.gray_1000, 183 + 184 + primary_25: BRAND.primaryLightTint, 185 + primary_50: color.primary_50, 186 + primary_100: color.primary_100, 187 + primary_200: color.primary_200, 188 + primary_300: color.primary_300, 189 + primary_400: color.primary_400, 190 + primary_500: BRAND.primaryLight, 191 + primary_600: color.primary_600, 192 + primary_700: color.primary_700, 193 + primary_800: color.primary_800, 194 + primary_900: color.primary_900, 195 + primary_950: color.primary_950, 196 + primary_975: color.primary_975, 197 + 198 + positive_25: color.green_25, 199 + positive_50: color.green_50, 200 + positive_100: color.green_100, 201 + positive_200: color.green_200, 202 + positive_300: color.green_300, 203 + positive_400: color.green_400, 204 + positive_500: '#61C554', 205 + positive_600: color.green_700, 206 + positive_700: color.green_700, 207 + positive_800: color.green_800, 208 + positive_900: color.green_900, 209 + positive_950: color.green_950, 210 + positive_975: color.green_975, 211 + 212 + negative_25: color.red_25, 213 + negative_50: color.red_50, 214 + negative_100: color.red_100, 215 + negative_200: color.red_200, 216 + negative_300: color.red_300, 217 + negative_400: color.red_400, 218 + negative_500: color.red_500, 219 + negative_600: color.red_600, 220 + negative_700: color.red_700, 221 + negative_800: color.red_800, 222 + negative_900: color.red_900, 223 + negative_950: color.red_950, 224 + negative_975: color.red_975, 225 + } as const 226 + 227 + const darkPalette: Palette = { 228 + white: BRAND.white, 229 + black: BRAND.black, 230 + like: color.like, 231 + 232 + contrast_0: color.gray_1000, 233 + contrast_25: color.gray_975, 234 + contrast_50: color.gray_950, 235 + contrast_100: color.gray_900, 236 + contrast_200: color.gray_800, 237 + contrast_300: color.gray_700, 238 + contrast_400: color.gray_600, 239 + contrast_500: color.gray_500, 240 + contrast_600: color.gray_400, 241 + contrast_700: color.gray_300, 242 + contrast_800: color.gray_200, 243 + contrast_900: color.gray_100, 244 + contrast_950: color.gray_50, 245 + contrast_975: color.gray_25, 246 + contrast_1000: color.gray_0, 247 + 248 + primary_25: BRAND.primaryDarkTint, 249 + primary_50: color.primary_950, 250 + primary_100: color.primary_900, 251 + primary_200: color.primary_800, 252 + primary_300: color.primary_700, 253 + primary_400: color.primary_600, 254 + primary_500: BRAND.primaryDark, 255 + primary_600: color.primary_400, 256 + primary_700: color.primary_300, 257 + primary_800: color.primary_200, 258 + primary_900: color.primary_100, 259 + primary_950: color.primary_50, 260 + primary_975: color.primary_25, 261 + 262 + positive_25: color.green_975, 263 + positive_50: color.green_950, 264 + positive_100: color.green_900, 265 + positive_200: color.green_800, 266 + positive_300: color.green_700, 267 + positive_400: color.green_600, 268 + positive_500: color.green_500, 269 + positive_600: color.green_400, 270 + positive_700: color.green_300, 271 + positive_800: color.green_200, 272 + positive_900: color.green_100, 273 + positive_950: color.green_50, 274 + positive_975: color.green_25, 275 + 276 + negative_25: color.red_975, 277 + negative_50: color.red_950, 278 + negative_100: color.red_900, 279 + negative_200: color.red_800, 280 + negative_300: color.red_700, 281 + negative_400: color.red_600, 282 + negative_500: color.red_500, 283 + negative_600: color.red_400, 284 + negative_700: color.red_300, 285 + negative_800: color.red_200, 286 + negative_900: color.red_100, 287 + negative_950: color.red_50, 288 + negative_975: color.red_25, 289 + } as const 290 + 291 + const dimPalette: Palette = { 292 + ...darkPalette, 293 + black: BRAND.twilight, 294 + like: color.like, 295 + 296 + contrast_0: `hsl(${hues.primary}, 28%, ${dimScale[0]}%)`, 297 + contrast_25: `hsl(${hues.primary}, 28%, ${dimScale[1]}%)`, 298 + contrast_50: `hsl(${hues.primary}, 28%, ${dimScale[2]}%)`, 299 + contrast_100: `hsl(${hues.primary}, 28%, ${dimScale[3]}%)`, 300 + contrast_200: `hsl(${hues.primary}, 28%, ${dimScale[4]}%)`, 301 + contrast_300: `hsl(${hues.primary}, 24%, ${dimScale[5]}%)`, 302 + contrast_400: `hsl(${hues.primary}, 24%, ${dimScale[6]}%)`, 303 + contrast_500: `hsl(${hues.primary}, 20%, ${dimScale[7]}%)`, 304 + contrast_600: `hsl(${hues.primary}, 20%, ${dimScale[8]}%)`, 305 + contrast_700: `hsl(${hues.primary}, 20%, ${dimScale[9]}%)`, 306 + contrast_800: `hsl(${hues.primary}, 20%, ${dimScale[10]}%)`, 307 + contrast_900: `hsl(${hues.primary}, 20%, ${dimScale[11]}%)`, 308 + contrast_950: `hsl(${hues.primary}, 20%, ${dimScale[12]}%)`, 309 + contrast_975: `hsl(${hues.primary}, 20%, ${dimScale[13]}%)`, 310 + contrast_1000: `hsl(${hues.primary}, 20%, ${dimScale[14]}%)`, 311 + 312 + primary_25: `hsl(240, 15%, ${dimScale[1]}%)`, 313 + primary_50: `hsl(240, 18%, ${dimScale[2]}%)`, 314 + primary_100: `hsl(240, 22%, ${dimScale[3]}%)`, 315 + primary_200: `hsl(240, 25%, ${dimScale[4]}%)`, 316 + primary_300: `hsl(240, 28%, ${dimScale[5]}%)`, 317 + primary_400: `hsl(240, 32%, ${dimScale[6]}%)`, 318 + primary_500: `hsl(240, 35%, ${dimScale[7]}%)`, 319 + primary_600: `hsl(240, 38%, ${dimScale[8]}%)`, 320 + primary_700: `hsl(240, 42%, ${dimScale[9]}%)`, 321 + primary_800: `hsl(240, 45%, ${dimScale[10]}%)`, 322 + primary_900: `hsl(240, 48%, ${dimScale[11]}%)`, 323 + primary_950: `hsl(240, 50%, ${dimScale[12]}%)`, 324 + primary_975: `hsl(240, 55%, ${dimScale[13]}%)`, 325 + 326 + positive_25: `hsl(${hues.positive}, 50%, ${dimScale[1]}%)`, 327 + positive_50: `hsl(${hues.positive}, 60%, ${dimScale[2]}%)`, 328 + positive_100: `hsl(${hues.positive}, 70%, ${dimScale[3]}%)`, 329 + positive_200: `hsl(${hues.positive}, 82%, ${dimScale[4]}%)`, 330 + positive_300: `hsl(${hues.positive}, 82%, ${dimScale[5]}%)`, 331 + positive_400: `hsl(${hues.positive}, 82%, ${dimScale[6]}%)`, 332 + positive_500: `hsl(${hues.positive}, 82%, ${dimScale[7]}%)`, 333 + positive_600: `hsl(${hues.positive}, 82%, ${dimScale[8]}%)`, 334 + positive_700: `hsl(${hues.positive}, 82%, ${dimScale[9]}%)`, 335 + positive_800: `hsl(${hues.positive}, 82%, ${dimScale[10]}%)`, 336 + positive_900: `hsl(${hues.positive}, 82%, ${dimScale[11]}%)`, 337 + positive_950: `hsl(${hues.positive}, 82%, ${dimScale[12]}%)`, 338 + positive_975: `hsl(${hues.positive}, 82%, ${dimScale[13]}%)`, 339 + 340 + negative_25: `hsl(${hues.negative}, 70%, ${dimScale[1]}%)`, 341 + negative_50: `hsl(${hues.negative}, 80%, ${dimScale[2]}%)`, 342 + negative_100: `hsl(${hues.negative}, 84%, ${dimScale[3]}%)`, 343 + negative_200: `hsl(${hues.negative}, 88%, ${dimScale[4]}%)`, 344 + negative_300: `hsl(${hues.negative}, 91%, ${dimScale[5]}%)`, 345 + negative_400: `hsl(${hues.negative}, 91%, ${dimScale[6]}%)`, 346 + negative_500: `hsl(${hues.negative}, 91%, ${dimScale[7]}%)`, 347 + negative_600: `hsl(${hues.negative}, 91%, ${dimScale[8]}%)`, 348 + negative_700: `hsl(${hues.negative}, 91%, ${dimScale[9]}%)`, 349 + negative_800: `hsl(${hues.negative}, 91%, ${dimScale[10]}%)`, 350 + negative_900: `hsl(${hues.negative}, 91%, ${dimScale[11]}%)`, 351 + negative_950: `hsl(${hues.negative}, 91%, ${dimScale[12]}%)`, 352 + negative_975: `hsl(${hues.negative}, 91%, ${dimScale[13]}%)`, 353 + } as const 354 + 355 + const light: Theme = { 356 + scheme: 'light', 357 + name: 'light', 358 + palette: lightPalette, 359 + atoms: { 360 + text: { 361 + color: lightPalette.black, 362 + }, 363 + text_contrast_low: { 364 + color: lightPalette.contrast_400, 365 + }, 366 + text_contrast_medium: { 367 + color: lightPalette.contrast_700, 368 + }, 369 + text_contrast_high: { 370 + color: lightPalette.contrast_900, 371 + }, 372 + text_inverted: { 373 + color: lightPalette.white, 374 + }, 375 + bg: { 376 + backgroundColor: lightPalette.white, 377 + }, 378 + bg_contrast_25: { 379 + backgroundColor: `hsl(${hues.primary}, 20%, ${defaultScale[13]}%)`, 380 + }, 381 + bg_contrast_50: { 382 + backgroundColor: `hsl(${hues.primary}, 20%, ${defaultScale[12]}%)`, 383 + }, 384 + bg_contrast_100: { 385 + backgroundColor: `hsl(${hues.primary}, 20%, ${defaultScale[11]}%)`, 386 + }, 387 + bg_contrast_200: { 388 + backgroundColor: lightPalette.contrast_200, 389 + }, 390 + bg_contrast_300: { 391 + backgroundColor: lightPalette.contrast_300, 392 + }, 393 + bg_contrast_400: { 394 + backgroundColor: lightPalette.contrast_400, 395 + }, 396 + bg_contrast_500: { 397 + backgroundColor: lightPalette.contrast_500, 398 + }, 399 + bg_contrast_600: { 400 + backgroundColor: lightPalette.contrast_600, 401 + }, 402 + bg_contrast_700: { 403 + backgroundColor: lightPalette.contrast_700, 404 + }, 405 + bg_contrast_800: { 406 + backgroundColor: lightPalette.contrast_800, 407 + }, 408 + bg_contrast_900: { 409 + backgroundColor: lightPalette.contrast_900, 410 + }, 411 + bg_contrast_950: { 412 + backgroundColor: lightPalette.contrast_950, 413 + }, 414 + bg_contrast_975: { 415 + backgroundColor: lightPalette.contrast_975, 416 + }, 417 + border_contrast_low: { 418 + borderColor: lightPalette.contrast_100, 419 + }, 420 + border_contrast_medium: { 421 + borderColor: lightPalette.contrast_200, 422 + }, 423 + border_contrast_high: { 424 + borderColor: lightPalette.contrast_300, 425 + }, 426 + shadow_sm: { 427 + ...atoms.shadow_sm, 428 + shadowColor: lightPalette.black, 429 + }, 430 + shadow_md: { 431 + ...atoms.shadow_md, 432 + shadowColor: lightPalette.black, 433 + }, 434 + shadow_lg: { 435 + ...atoms.shadow_lg, 436 + shadowColor: lightPalette.black, 437 + }, 438 + }, 439 + } 440 + 441 + const dark: Theme = { 442 + scheme: 'dark', 443 + name: 'dark', 444 + palette: darkPalette, 445 + atoms: { 446 + text: { 447 + color: darkPalette.white, 448 + }, 449 + text_contrast_low: { 450 + color: darkPalette.contrast_400, 451 + }, 452 + text_contrast_medium: { 453 + color: darkPalette.contrast_600, 454 + }, 455 + text_contrast_high: { 456 + color: darkPalette.contrast_900, 457 + }, 458 + text_inverted: { 459 + color: darkPalette.black, 460 + }, 461 + bg: { 462 + backgroundColor: darkPalette.black, 463 + }, 464 + bg_contrast_25: { 465 + backgroundColor: `hsl(${hues.primary}, 28%, ${defaultScale[1]}%)`, 466 + }, 467 + bg_contrast_50: { 468 + backgroundColor: `hsl(${hues.primary}, 28%, ${defaultScale[2]}%)`, 469 + }, 470 + bg_contrast_100: { 471 + backgroundColor: `hsl(${hues.primary}, 28%, ${defaultScale[3]}%)`, 472 + }, 473 + bg_contrast_200: { 474 + backgroundColor: darkPalette.contrast_200, 475 + }, 476 + bg_contrast_300: { 477 + backgroundColor: darkPalette.contrast_300, 478 + }, 479 + bg_contrast_400: { 480 + backgroundColor: darkPalette.contrast_400, 481 + }, 482 + bg_contrast_500: { 483 + backgroundColor: darkPalette.contrast_500, 484 + }, 485 + bg_contrast_600: { 486 + backgroundColor: darkPalette.contrast_600, 487 + }, 488 + bg_contrast_700: { 489 + backgroundColor: darkPalette.contrast_700, 490 + }, 491 + bg_contrast_800: { 492 + backgroundColor: darkPalette.contrast_800, 493 + }, 494 + bg_contrast_900: { 495 + backgroundColor: darkPalette.contrast_900, 496 + }, 497 + bg_contrast_950: { 498 + backgroundColor: darkPalette.contrast_950, 499 + }, 500 + bg_contrast_975: { 501 + backgroundColor: darkPalette.contrast_975, 502 + }, 503 + border_contrast_low: { 504 + borderColor: darkPalette.contrast_100, 505 + }, 506 + border_contrast_medium: { 507 + borderColor: darkPalette.contrast_200, 508 + }, 509 + border_contrast_high: { 510 + borderColor: darkPalette.contrast_300, 511 + }, 512 + shadow_sm: { 513 + ...atoms.shadow_sm, 514 + shadowOpacity: 0.7, 515 + shadowColor: color.trueBlack, 516 + }, 517 + shadow_md: { 518 + ...atoms.shadow_md, 519 + shadowOpacity: 0.7, 520 + shadowColor: color.trueBlack, 521 + }, 522 + shadow_lg: { 523 + ...atoms.shadow_lg, 524 + shadowOpacity: 0.7, 525 + shadowColor: color.trueBlack, 526 + }, 527 + }, 528 + } 529 + 530 + const dim: Theme = { 531 + ...dark, 532 + scheme: 'dark', 533 + name: 'dim', 534 + palette: dimPalette, 535 + atoms: { 536 + ...dark.atoms, 537 + text: { 538 + color: dimPalette.white, 539 + }, 540 + text_contrast_low: { 541 + color: dimPalette.contrast_400, 542 + }, 543 + text_contrast_medium: { 544 + color: dimPalette.contrast_600, 545 + }, 546 + text_contrast_high: { 547 + color: dimPalette.contrast_900, 548 + }, 549 + text_inverted: { 550 + color: dimPalette.black, 551 + }, 552 + bg: { 553 + backgroundColor: dimPalette.black, 554 + }, 555 + bg_contrast_25: { 556 + backgroundColor: dimPalette.contrast_25, 557 + }, 558 + bg_contrast_50: { 559 + backgroundColor: dimPalette.contrast_50, 560 + }, 561 + bg_contrast_100: { 562 + backgroundColor: dimPalette.contrast_100, 563 + }, 564 + bg_contrast_200: { 565 + backgroundColor: dimPalette.contrast_200, 566 + }, 567 + bg_contrast_300: { 568 + backgroundColor: dimPalette.contrast_300, 569 + }, 570 + bg_contrast_400: { 571 + backgroundColor: dimPalette.contrast_400, 572 + }, 573 + bg_contrast_500: { 574 + backgroundColor: dimPalette.contrast_500, 575 + }, 576 + bg_contrast_600: { 577 + backgroundColor: dimPalette.contrast_600, 578 + }, 579 + bg_contrast_700: { 580 + backgroundColor: dimPalette.contrast_700, 581 + }, 582 + bg_contrast_800: { 583 + backgroundColor: dimPalette.contrast_800, 584 + }, 585 + bg_contrast_900: { 586 + backgroundColor: dimPalette.contrast_900, 587 + }, 588 + bg_contrast_950: { 589 + backgroundColor: dimPalette.contrast_950, 590 + }, 591 + bg_contrast_975: { 592 + backgroundColor: dimPalette.contrast_975, 593 + }, 594 + border_contrast_low: { 595 + borderColor: dimPalette.contrast_100, 596 + }, 597 + border_contrast_medium: { 598 + borderColor: dimPalette.contrast_200, 599 + }, 600 + border_contrast_high: { 601 + borderColor: dimPalette.contrast_300, 602 + }, 603 + shadow_sm: { 604 + ...atoms.shadow_sm, 605 + shadowOpacity: 0.7, 606 + shadowColor: `hsl(${hues.primary}, 28%, 6%)`, 607 + }, 608 + shadow_md: { 609 + ...atoms.shadow_md, 610 + shadowOpacity: 0.7, 611 + shadowColor: `hsl(${hues.primary}, 28%, 6%)`, 612 + }, 613 + shadow_lg: { 614 + ...atoms.shadow_lg, 615 + shadowOpacity: 0.7, 616 + shadowColor: `hsl(${hues.primary}, 28%, 6%)`, 617 + }, 618 + }, 619 + } 620 + 621 + return { 622 + lightPalette, 623 + darkPalette, 624 + dimPalette, 625 + light, 626 + dark, 627 + dim, 628 + } 629 + }
+45 -4
src/alf/util/colorGeneration.ts
··· 1 - import {utils} from '@bsky.app/alf' 1 + import {logger} from '#/logger' 2 2 3 - export const BLUE_HUE = 211 3 + export const BLUE_HUE = 240 4 + export const RED_HUE = 0 5 + export const GREEN_HUE = 80 4 6 5 7 /** 6 - * @deprecated use `utils.alpha` from `@bsky.app/alf` instead 8 + * Smooth progression of lightness "stops" for generating HSL colors. 7 9 */ 8 - export const transparentifyColor = utils.alpha 10 + export const COLOR_STOPS = [ 11 + 0, 0.05, 0.1, 0.15, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.85, 0.9, 0.95, 1, 12 + ] 13 + 14 + export function generateScale(start: number, end: number) { 15 + const range = end - start 16 + return COLOR_STOPS.map(stop => { 17 + return start + range * stop 18 + }) 19 + } 20 + 21 + export const defaultScale = generateScale(6, 100) 22 + // dim shifted 6% lighter 23 + export const dimScale = generateScale(12, 100) 24 + 25 + export function transparentifyColor(color: string, alpha: number) { 26 + if (color.startsWith('hsl(')) { 27 + return 'hsla(' + color.slice('hsl('.length, -1) + `, ${alpha})` 28 + } else if (color.startsWith('rgb(')) { 29 + return 'rgba(' + color.slice('rgb('.length, -1) + `, ${alpha})` 30 + } else if (color.startsWith('#')) { 31 + if (color.length === 7) { 32 + const alphaHex = Math.round(alpha * 255).toString(16) 33 + // Per MDN: If there is only one number, it is duplicated: e means ee 34 + // https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color 35 + return color.slice(0, 7) + alphaHex.padStart(2, alphaHex) 36 + } else if (color.length === 4) { 37 + // convert to 6-digit hex before adding alpha 38 + const [r, g, b] = color.slice(1).split('') 39 + const alphaHex = Math.round(alpha * 255).toString(16) 40 + return `#${r.repeat(2)}${g.repeat(2)}${b.repeat(2)}${alphaHex.padStart( 41 + 2, 42 + alphaHex, 43 + )}` 44 + } 45 + } else { 46 + logger.warn(`Could not make '${color}' transparent`) 47 + } 48 + return color 49 + }
+9 -8
src/lib/constants.ts
··· 190 190 website: { 191 191 blog: { 192 192 findFriendsAnnouncement: 193 - 'https://bsky.social/about/blog/12-16-2025-find-friends', 194 - initialVerificationAnnouncement: `https://bsky.social/about/blog/04-21-2025-verification`, 195 - searchTipsAndTricks: 'https://bsky.social/about/blog/05-31-2024-search', 193 + 'https://www.blackskyweb.xyz/about/blog/12-16-2025-find-friends', 194 + initialVerificationAnnouncement: `https://www.blackskyweb.xyz/about/blog/04-21-2025-verification`, 195 + searchTipsAndTricks: 196 + 'https://www.blackskyweb.xyz/about/blog/05-31-2024-search', 196 197 }, 197 198 support: { 198 199 findFriendsPrivacyPolicy: 199 - 'https://bsky.social/about/support/find-friends-privacy-policy', 200 + 'https://www.blackskyweb.xyz/about/support/find-friends-privacy-policy', 200 201 }, 201 202 }, 202 203 } ··· 232 233 } 233 234 234 235 export const webLinks = { 235 - tos: `https://bsky.social/about/support/tos`, 236 - privacy: `https://bsky.social/about/support/privacy-policy`, 237 - community: `https://bsky.social/about/support/community-guidelines`, 238 - communityDeprecated: `https://bsky.social/about/support/community-guidelines-deprecated`, 236 + tos: `https://www.blackskyweb.xyz/about/support/tos`, 237 + privacy: `https://www.blackskyweb.xyz/about/support/privacy-policy`, 238 + community: `https://www.blackskyweb.xyz/about/support/community-guidelines`, 239 + communityDeprecated: `https://www.blackskyweb.xyz/about/support/community-guidelines-deprecated`, 239 240 }
+2 -12
src/screens/Settings/AboutSettings.tsx
··· 7 7 import {type NativeStackScreenProps} from '@react-navigation/native-stack' 8 8 import {useMutation} from '@tanstack/react-query' 9 9 10 - import {STATUS_PAGE_URL} from '#/lib/constants' 11 10 import {type CommonNavigatorParams} from '#/lib/routes/types' 12 11 import * as Toast from '#/view/com/util/Toast' 13 12 import * as SettingsList from '#/screens/Settings/components/SettingsList' 14 13 import {Atom_Stroke2_Corner0_Rounded as AtomIcon} from '#/components/icons/Atom' 15 14 import {BroomSparkle_Stroke2_Corner2_Rounded as BroomSparkleIcon} from '#/components/icons/BroomSparkle' 16 15 import {CodeLines_Stroke2_Corner2_Rounded as CodeLinesIcon} from '#/components/icons/CodeLines' 17 - import {Globe_Stroke2_Corner0_Rounded as GlobeIcon} from '#/components/icons/Globe' 18 16 import {Newspaper_Stroke2_Corner2_Rounded as NewspaperIcon} from '#/components/icons/Newspaper' 19 17 import {Wrench_Stroke2_Corner2_Rounded as WrenchIcon} from '#/components/icons/Wrench' 20 18 import * as Layout from '#/components/Layout' ··· 78 76 <Layout.Content> 79 77 <SettingsList.Container> 80 78 <SettingsList.LinkItem 81 - to="https://bsky.social/about/support/tos" 79 + to="https://www.blackskyweb.xyz/about/support/tos" 82 80 label={_(msg`Terms of Service`)}> 83 81 <SettingsList.ItemIcon icon={NewspaperIcon} /> 84 82 <SettingsList.ItemText> ··· 86 84 </SettingsList.ItemText> 87 85 </SettingsList.LinkItem> 88 86 <SettingsList.LinkItem 89 - to="https://bsky.social/about/support/privacy-policy" 87 + to="https://www.blackskyweb.xyz/about/support/privacy-policy" 90 88 label={_(msg`Privacy Policy`)}> 91 89 <SettingsList.ItemIcon icon={NewspaperIcon} /> 92 90 <SettingsList.ItemText> 93 91 <Trans>Privacy Policy</Trans> 94 - </SettingsList.ItemText> 95 - </SettingsList.LinkItem> 96 - <SettingsList.LinkItem 97 - to={STATUS_PAGE_URL} 98 - label={_(msg`Status Page`)}> 99 - <SettingsList.ItemIcon icon={GlobeIcon} /> 100 - <SettingsList.ItemText> 101 - <Trans>Status Page</Trans> 102 92 </SettingsList.ItemText> 103 93 </SettingsList.LinkItem> 104 94 <SettingsList.Divider />
+45 -2
src/style.css
··· 11 11 * 12 12 * HTML & BODY STYLES IN `web/index.html` and `bskyweb/templates/base.html` 13 13 */ 14 + :root { 15 + --text: #070c0c; 16 + --background: #f8faf9; 17 + --backgroundLight: hsl(240, 20%, 95%); 18 + } 19 + @media (prefers-color-scheme: dark) { 20 + :root { 21 + color-scheme: dark; 22 + --text: #f8faf9; 23 + --background: #070c0c; 24 + --backgroundLight: hsl(240, 20%, 20%); 25 + } 26 + } 27 + 28 + html.theme--light { 29 + --text: #070c0c; 30 + --background: #f8faf9; 31 + --backgroundLight: hsl(240, 20%, 95%); 32 + background-color: #f8faf9; 33 + ::selection { 34 + background: #d2fc51; 35 + } 36 + } 37 + html.theme--dark { 38 + color-scheme: dark; 39 + background-color: #070c0c; 40 + --text: #f8faf9; 41 + --background: #070c0c; 42 + --backgroundLight: hsl(240, 20%, 20%); 43 + ::selection { 44 + background: #464985; 45 + } 46 + } 47 + html.theme--dim { 48 + color-scheme: dark; 49 + background-color: #161e27; 50 + --text: #f8faf9; 51 + --background: #161e27; 52 + --backgroundLight: hsl(240, 20%, 10%); 53 + ::selection { 54 + background: #464985; 55 + } 56 + } 14 57 15 58 /* Buttons and inputs have a font set by UA, so we'll have to reset that */ 16 59 button, ··· 75 118 pointer-events: none; 76 119 } 77 120 .ProseMirror .mention { 78 - color: #0085ff; 121 + color: rgb(96, 96, 233); 79 122 } 80 123 .ProseMirror a, 81 124 .ProseMirror .autolink { 82 - color: #0085ff; 125 + color: rgb(96, 96, 233); 83 126 } 84 127 /* OLLIE: TODO -- this is not accessible */ 85 128 /* Remove focus state on inputs */
+36 -15
src/view/com/auth/SplashScreen.web.tsx
··· 86 86 ]}> 87 87 <ErrorBoundary> 88 88 <View style={[a.justify_center, a.align_center]}> 89 - <Logo width={kawaii ? 300 : 92} fill="sky" /> 89 + <Logo width={kawaii ? 300 : 92} fill={t.atoms.text.color} /> 90 90 91 91 {!kawaii && ( 92 92 <View style={[a.pb_sm, a.pt_5xl]}> ··· 100 100 a.font_semi_bold, 101 101 t.atoms.text_contrast_medium, 102 102 ]}> 103 - <Trans>What's up?</Trans> 103 + <Trans>What's poppin'?</Trans> 104 104 </Text> 105 105 </View> 106 106 ··· 112 112 onPress={onPressCreateAccount} 113 113 label={_(msg`Create new account`)} 114 114 accessibilityHint={_( 115 - msg`Opens flow to create a new Bluesky account`, 115 + msg`Opens flow to create a new Blacksky account`, 116 116 )} 117 117 size="large" 118 118 variant="solid" ··· 126 126 onPress={onPressSignin} 127 127 label={_(msg`Sign in`)} 128 128 accessibilityHint={_( 129 - msg`Opens flow to sign in to your existing Bluesky account`, 129 + msg`Opens flow to sign in to your existing Blacksky account`, 130 130 )} 131 131 size="large" 132 132 variant="solid" ··· 135 135 <Trans>Sign in</Trans> 136 136 </ButtonText> 137 137 </Button> 138 + <Text 139 + style={[ 140 + a.text_sm, 141 + a.leading_snug, 142 + t.atoms.text_contrast_medium, 143 + a.pt_md, 144 + ]}> 145 + <Trans> 146 + Migrating from Bluesky? Use{' '} 147 + <InlineLinkText 148 + label={_(msg`Tektite.cc`)} 149 + to="https://tektite.cc" 150 + style={[a.text_sm]}> 151 + Tektite.cc 152 + </InlineLinkText>{' '} 153 + to move your followers, posts, and media to Blacksky. 154 + </Trans> 155 + </Text> 138 156 </View> 139 157 </ErrorBoundary> 140 158 </View> ··· 169 187 t.atoms.border_contrast_medium, 170 188 ]}> 171 189 <InlineLinkText 172 - label={_(msg`Learn more about Bluesky`)} 173 - to="https://bsky.social"> 174 - <Trans>Business</Trans> 190 + label={_(msg`Learn more about Blacksky`)} 191 + to="https://www.blackskyweb.xyz"> 192 + <Trans>About</Trans> 193 + </InlineLinkText> 194 + <InlineLinkText 195 + label={_(msg`Blacksky Terms of Service`)} 196 + to="https://www.blackskyweb.xyz/about/support/tos"> 197 + <Trans>Terms</Trans> 175 198 </InlineLinkText> 176 199 <InlineLinkText 177 - label={_(msg`Read the Bluesky blog`)} 178 - to="https://bsky.social/about/blog"> 179 - <Trans>Blog</Trans> 200 + label={_(msg`Blacksky Privacy Policy`)} 201 + to="https://www.blackskyweb.xyz/about/support/privacy-policy"> 202 + <Trans>Privacy</Trans> 180 203 </InlineLinkText> 181 204 <InlineLinkText 182 - label={_(msg`See jobs at Bluesky`)} 183 - to="https://bsky.social/about/join"> 184 - <Trans comment="Link to a page with job openings at Bluesky"> 185 - Jobs 186 - </Trans> 205 + label={_(msg`Blacksky on GitHub`)} 206 + to="https://github.com/blacksky-algorithms"> 207 + <Trans>GitHub</Trans> 187 208 </InlineLinkText> 188 209 189 210 <View style={a.flex_1} />
+3 -3
src/view/com/util/UserAvatar.tsx
··· 119 119 fill="none" 120 120 stroke="none" 121 121 style={aviStyle}> 122 - <Rect width="32" height="32" rx="4" fill="#0070FF" /> 122 + <Rect width="32" height="32" rx="4" fill="#6060E9" /> 123 123 <Path 124 124 d="M13.5 7.25C13.5 6.55859 14.0586 6 14.75 6C20.9648 6 26 11.0352 26 17.25C26 17.9414 25.4414 18.5 24.75 18.5C24.0586 18.5 23.5 17.9414 23.5 17.25C23.5 12.418 19.582 8.5 14.75 8.5C14.0586 8.5 13.5 7.94141 13.5 7.25ZM8.36719 14.6172L12.4336 18.6836L13.543 17.5742C13.5156 17.4727 13.5 17.3633 13.5 17.25C13.5 16.5586 14.0586 16 14.75 16C15.4414 16 16 16.5586 16 17.25C16 17.9414 15.4414 18.5 14.75 18.5C14.6367 18.5 14.5312 18.4844 14.4258 18.457L13.3164 19.5664L17.3828 23.6328C17.9492 24.1992 17.8438 25.1484 17.0977 25.4414C16.1758 25.8008 15.1758 26 14.125 26C9.63672 26 6 22.3633 6 17.875C6 16.8242 6.19922 15.8242 6.5625 14.9023C6.85547 14.1602 7.80469 14.0508 8.37109 14.6172H8.36719ZM14.75 9.75C18.8906 9.75 22.25 13.1094 22.25 17.25C22.25 17.9414 21.6914 18.5 21 18.5C20.3086 18.5 19.75 17.9414 19.75 17.25C19.75 14.4883 17.5117 12.25 14.75 12.25C14.0586 12.25 13.5 11.6914 13.5 11C13.5 10.3086 14.0586 9.75 14.75 9.75Z" 125 125 fill="white" ··· 141 141 style={aviStyle}> 142 142 <Path 143 143 d="M28 0H4C1.79086 0 0 1.79086 0 4V28C0 30.2091 1.79086 32 4 32H28C30.2091 32 32 30.2091 32 28V4C32 1.79086 30.2091 0 28 0Z" 144 - fill="#0070FF" 144 + fill="#6060E9" 145 145 /> 146 146 <Path 147 147 d="M22.1529 22.3542C23.4522 22.4603 24.7593 22.293 25.9899 21.8629C26.0369 21.2838 25.919 20.7032 25.6497 20.1884C25.3805 19.6735 24.9711 19.2454 24.4687 18.9535C23.9663 18.6617 23.3916 18.518 22.8109 18.5392C22.2303 18.5603 21.6676 18.7454 21.1878 19.0731M22.1529 22.3542C22.1489 21.1917 21.8142 20.0534 21.1878 19.0741ZM10.8111 19.0741C10.3313 18.7468 9.7687 18.5619 9.18826 18.5409C8.60781 18.5199 8.03327 18.6636 7.53107 18.9554C7.02888 19.2472 6.61953 19.6752 6.35036 20.1899C6.08119 20.7046 5.96319 21.285 6.01001 21.8639C7.23969 22.2964 8.5461 22.4632 9.84497 22.3531M10.8111 19.0741C10.1851 20.0535 9.84865 21.1908 9.84497 22.3531ZM19.0759 10.077C19.0759 10.8931 18.7518 11.6757 18.1747 12.2527C17.5977 12.8298 16.815 13.154 15.9989 13.154C15.1829 13.154 14.4002 12.8298 13.8232 12.2527C13.2461 11.6757 12.922 10.8931 12.922 10.077C12.922 9.26092 13.2461 8.47828 13.8232 7.90123C14.4002 7.32418 15.1829 7 15.9989 7C16.815 7 17.5977 7.32418 18.1747 7.90123C18.7518 8.47828 19.0759 9.26092 19.0759 10.077ZM25.2299 13.154C25.2299 13.457 25.1702 13.7571 25.0542 14.0371C24.9383 14.3171 24.7683 14.5715 24.554 14.7858C24.3397 15.0001 24.0853 15.1701 23.8053 15.2861C23.5253 15.402 23.2252 15.4617 22.9222 15.4617C22.6191 15.4617 22.319 15.402 22.039 15.2861C21.759 15.1701 21.5046 15.0001 21.2903 14.7858C21.0761 14.5715 20.9061 14.3171 20.7901 14.0371C20.6741 13.7571 20.6144 13.457 20.6144 13.154C20.6144 12.5419 20.8576 11.9549 21.2903 11.5222C21.7231 11.0894 22.3101 10.8462 22.9222 10.8462C23.5342 10.8462 24.1212 11.0894 24.554 11.5222C24.9868 11.9549 25.2299 12.5419 25.2299 13.154ZM11.3835 13.154C11.3835 13.457 11.3238 13.7571 11.2078 14.0371C11.0918 14.3171 10.9218 14.5715 10.7075 14.7858C10.4932 15.0001 10.2388 15.1701 9.95886 15.2861C9.67887 15.402 9.37878 15.4617 9.07572 15.4617C8.77266 15.4617 8.47257 15.402 8.19259 15.2861C7.9126 15.1701 7.6582 15.0001 7.4439 14.7858C7.22961 14.5715 7.05962 14.3171 6.94365 14.0371C6.82767 13.7571 6.76798 13.457 6.76798 13.154C6.76798 12.5419 7.01112 11.9549 7.4439 11.5222C7.87669 11.0894 8.46367 10.8462 9.07572 10.8462C9.68777 10.8462 10.2748 11.0894 10.7075 11.5222C11.1403 11.9549 11.3835 12.5419 11.3835 13.154Z" ··· 196 196 fill="none" 197 197 stroke="none" 198 198 style={aviStyle}> 199 - <Circle cx="12" cy="12" r="12" fill="#0070ff" /> 199 + <Circle cx="12" cy="12" r="12" fill="#6060E9" /> 200 200 <Circle cx="12" cy="9.5" r="3.5" fill="#fff" /> 201 201 <Path 202 202 strokeLinecap="round"
+35 -7
src/view/icons/Logomark.tsx
··· 1 - import Svg, {Path, type PathProps, type SvgProps} from 'react-native-svg' 1 + import Svg, { 2 + ClipPath, 3 + Defs, 4 + G, 5 + Path, 6 + type PathProps, 7 + Rect, 8 + type SvgProps, 9 + } from 'react-native-svg' 2 10 3 11 import {usePalette} from '#/lib/hooks/usePalette' 4 12 5 - const ratio = 54 / 61 13 + const ratio = 243 / 285 6 14 7 15 export function Logomark({ 8 16 fill, ··· 11 19 const pal = usePalette('default') 12 20 // @ts-ignore it's fiiiiine 13 21 const size = parseInt(rest.width || 32) 22 + const _fill = fill || pal.text.color 14 23 15 24 return ( 16 25 <Svg 17 26 fill="none" 18 - viewBox="0 0 61 54" 27 + viewBox="0 0 285 243" 19 28 {...rest} 20 29 width={size} 21 30 height={Number(size) * ratio}> 22 - <Path 23 - fill={fill || pal.text.color} 24 - d="M13.223 3.602C20.215 8.832 27.738 19.439 30.5 25.13c2.762-5.691 10.284-16.297 17.278-21.528C52.824-.172 61-3.093 61 6.2c0 1.856-1.068 15.59-1.694 17.82-2.178 7.752-10.112 9.73-17.17 8.532 12.337 2.092 15.475 9.021 8.697 15.95-12.872 13.159-18.5-3.302-19.943-7.52-.264-.773-.388-1.135-.39-.827-.002-.308-.126.054-.39.827-1.442 4.218-7.071 20.679-19.943 7.52-6.778-6.929-3.64-13.858 8.697-15.95-7.058 1.197-14.992-.78-17.17-8.532C1.068 21.79 0 8.056 0 6.2 0-3.093 8.176-.172 13.223 3.602Z" 25 - /> 31 + <G clipPath="url(#clip0_logomark)"> 32 + <Path 33 + fill={_fill} 34 + d="M148.846 144.562C148.846 159.75 161.158 172.062 176.346 172.062H207.012V185.865H176.346C161.158 185.865 148.846 198.177 148.846 213.365V243.045H136.029V213.365C136.029 198.177 123.717 185.865 108.529 185.865H77.8633V172.062H108.529C123.717 172.062 136.029 159.75 136.029 144.562V113.896H148.846V144.562Z" 35 + /> 36 + <Path 37 + fill={_fill} 38 + d="M170.946 31.8766C160.207 42.616 160.207 60.0281 170.946 70.7675L192.631 92.4516L182.871 102.212L161.186 80.5275C150.447 69.7881 133.035 69.7881 122.296 80.5275L101.309 101.514L92.2456 92.4509L113.232 71.4642C123.972 60.7248 123.972 43.3128 113.232 32.5733L91.5488 10.8899L101.309 1.12988L122.993 22.814C133.732 33.5533 151.144 33.5534 161.884 22.814L183.568 1.12988L192.631 10.1925L170.946 31.8766Z" 39 + /> 40 + <Path 41 + fill={_fill} 42 + d="M79.0525 75.3259C75.1216 89.9962 83.8276 105.076 98.498 109.006L128.119 116.943L124.547 130.275L94.9267 122.338C80.2564 118.407 65.1772 127.113 61.2463 141.784L53.5643 170.453L41.1837 167.136L48.8654 138.467C52.7963 123.797 44.0902 108.718 29.4199 104.787L-0.201172 96.8497L3.37124 83.5173L32.9923 91.4542C47.6626 95.3851 62.7419 86.679 66.6728 72.0088L74.6098 42.3877L86.9895 45.7048L79.0525 75.3259Z" 43 + /> 44 + <Path 45 + fill={_fill} 46 + d="M218.413 71.4229C222.344 86.093 237.423 94.7992 252.094 90.8683L281.715 82.9313L285.287 96.2628L255.666 104.2C240.995 108.131 232.29 123.21 236.22 137.88L243.902 166.55L231.522 169.867L223.841 141.198C219.91 126.528 204.831 117.822 190.16 121.753L160.539 129.69L156.967 116.357L186.588 108.42C201.258 104.49 209.964 89.4103 206.033 74.74L198.096 45.1189L210.476 41.8018L218.413 71.4229Z" 47 + /> 48 + </G> 49 + <Defs> 50 + <ClipPath id="clip0_logomark"> 51 + <Rect width="285" height="243" fill="white" /> 52 + </ClipPath> 53 + </Defs> 26 54 </Svg> 27 55 ) 28 56 }
+2 -2
src/view/screens/CommunityGuidelines.tsx
··· 42 42 The Community Guidelines have been moved to{' '} 43 43 <TextLink 44 44 style={pal.link} 45 - href="https://bsky.social/about/support/community-guidelines" 46 - text="bsky.social/about/support/community-guidelines" 45 + href="https://www.blackskyweb.xyz/about/support/community-guidelines" 46 + text="blackskyweb.xyz/about/support/community-guidelines" 47 47 /> 48 48 </Trans> 49 49 </Text>
+2 -2
src/view/screens/CopyrightPolicy.tsx
··· 39 39 The Copyright Policy has been moved to{' '} 40 40 <TextLink 41 41 style={pal.link} 42 - href="https://bsky.social/about/support/copyright" 43 - text="bsky.social/about/support/copyright" 42 + href="https://www.blackskyweb.xyz/about/support/copyright" 43 + text="blackskyweb.xyz/about/support/copyright" 44 44 /> 45 45 </Trans> 46 46 </Text>
+1 -1
src/view/shell/NavSignupCard.tsx
··· 37 37 <View style={[a.pt_lg]}> 38 38 <Text 39 39 style={[a.text_3xl, a.font_bold, {lineHeight: a.text_3xl.fontSize}]}> 40 - <Trans>Join the conversation</Trans> 40 + <Trans>Join the Cookout</Trans> 41 41 </Text> 42 42 </View> 43 43
-8
src/view/shell/index.web.tsx
··· 21 21 import {LinkWarningDialog} from '#/components/dialogs/LinkWarning' 22 22 import {MutedWordsDialog} from '#/components/dialogs/MutedWords' 23 23 import {SigninDialog} from '#/components/dialogs/Signin' 24 - import {useWelcomeModal} from '#/components/hooks/useWelcomeModal' 25 24 import {GlobalReportDialog} from '#/components/moderation/ReportDialog' 26 25 import {Outlet as PortalOutlet} from '#/components/Portal' 27 - import {WelcomeModal} from '#/components/WelcomeModal' 28 26 import {PassiveAnalytics} from '#/analytics/PassiveAnalytics' 29 27 import {FlatNavigator, RoutesContainer} from '#/Navigation' 30 28 import {Composer} from './Composer.web' ··· 33 31 function ShellInner() { 34 32 const navigator = useNavigation<NavigationProp>() 35 33 const closeAllActiveElements = useCloseAllActiveElements() 36 - const welcomeModalControl = useWelcomeModal() 37 - 38 34 useComposerKeyboardShortcut() 39 35 useIntentHandler() 40 36 ··· 64 60 <LinkWarningDialog /> 65 61 <Lightbox /> 66 62 <GlobalReportDialog /> 67 - 68 - {welcomeModalControl.isOpen && ( 69 - <WelcomeModal control={welcomeModalControl} /> 70 - )} 71 63 72 64 <PortalOutlet /> 73 65 </>
+52 -112
web/index.html
··· 2 2 <html> 3 3 <head> 4 4 <meta charset="utf-8"> 5 - <meta name="theme-color"> 5 + <meta name="theme-color" content="#6060E9"> 6 6 <!-- 7 7 This viewport works for phones with notches. 8 8 It's optimized for gestures by disabling global zoom. ··· 14 14 <!-- 15 15 Preconnect to essential domains 16 16 --> 17 - <link rel="preconnect" href="https://bsky.social"> 18 - <link rel="preconnect" href="https://go.bsky.app"> 17 + <link rel="preconnect" href="https://blacksky.community"> 18 + <link rel="preconnect" href="https://go.blacksky.community"> 19 19 <title>%WEB_TITLE%</title> 20 20 21 21 <link rel="preload" as="font" type="font/woff2" href="/static/media/InterVariable.c504db5c06caaf7cdfba.woff2" crossorigin> ··· 43 43 font-style: italic; 44 44 font-display: swap; 45 45 } 46 + html { 47 + background-color: #F8FAF9; 48 + color: #000000; 49 + } 50 + @media (prefers-color-scheme: dark) { 51 + html { 52 + background-color: #070C0C; 53 + color: #FFFFFF; 54 + } 55 + } 46 56 html, 47 57 body { 48 58 margin: 0px; ··· 57 67 -ms-overflow-style: scrollbar; 58 68 font-synthesis-weight: none; 59 69 } 60 - :root { 61 - --text: black; 62 - --background: white; 63 - --backgroundLight: #e2e7ee; 64 - } 65 - @media (prefers-color-scheme: dark) { 66 - :root { 67 - color-scheme: dark; 68 - --text: white; 69 - --background: black; 70 - --backgroundLight: #232e3e; 71 - } 72 - } 73 70 html, 74 71 body, 75 72 #root { ··· 78 75 min-height: 100%; 79 76 width: 100%; 80 77 } 81 - html.theme--light, 82 - html.theme--light body, 83 - html.theme--light #root { 84 - background-color: white; 85 - --text: black; 86 - --background: white; 87 - --backgroundLight: #DCE2EA; 88 - } 89 - html.theme--dark, 90 - html.theme--dark body, 91 - html.theme--dark #root { 92 - color-scheme: dark; 93 - background-color: black; 94 - --text: white; 95 - --background: black; 96 - --backgroundLight: #232E3E; 97 - } 98 - html.theme--dim, 99 - html.theme--dim body, 100 - html.theme--dim #root { 101 - color-scheme: dark; 102 - background-color: #151D28; 103 - --text: white; 104 - --background: #151D28; 105 - --backgroundLight: #2C3A4E; 106 - } 107 78 #splash { 108 - display: flex; 109 79 position: fixed; 110 - top: 0; 111 - bottom: 0; 112 - left: 0; 113 - right: 0; 114 - align-items: center; 115 - justify-content: center; 116 - } 117 - #splash svg { 118 - position: relative; 119 - top: -50px; 120 80 width: 100px; 81 + left: 50%; 82 + top: 50%; 83 + transform: translateX(-50%) translateY(-50%) translateY(-50px); 121 84 } 122 85 /** 123 86 * We need these styles to prevent shifting due to scrollbar show/hide on ··· 130 93 overflow-y: scroll; 131 94 } 132 95 </style> 133 - <script> 134 - const theme = localStorage.getItem('ALF_THEME') 135 - if (theme) { 136 - document.documentElement.classList.add(`theme--${theme}`) 137 - } 138 - </script> 139 96 </head> 140 97 141 98 <body> 142 - <!-- 143 - A generic no script element with a reload button and a message. 144 - Feel free to customize this however you'd like. 145 - --> 146 - <noscript> 147 - <form 148 - action="" 149 - style=" 150 - background-color: #fff; 151 - position: fixed; 152 - top: 0; 153 - left: 0; 154 - right: 0; 155 - bottom: 0; 156 - z-index: 9999; 157 - " 158 - > 159 - <div 160 - style=" 161 - font-size: 18px; 162 - font-family: Helvetica, sans-serif; 163 - line-height: 24px; 164 - margin: 10%; 165 - width: 80%; 166 - " 167 - > 168 - <p lang="en">Oh no! It looks like JavaScript is not enabled in your browser.</p> 169 - <p lang="en" style="margin: 20px 0;"> 170 - <button 171 - type="submit" 172 - style=" 173 - background-color: #4630eb; 174 - border-radius: 100px; 175 - border: none; 176 - box-shadow: none; 177 - color: #fff; 178 - cursor: pointer; 179 - font-weight: bold; 180 - line-height: 20px; 181 - padding: 6px 16px; 182 - " 183 - > 184 - Reload 185 - </button> 186 - </p> 187 - </div> 188 - </form> 189 - </noscript> 99 + <noscript style=" 100 + background-color: #fff; 101 + position: fixed; 102 + top: 0; 103 + left: 0; 104 + right: 0; 105 + bottom: 0; 106 + z-index: 9999; 107 + margin: 1em; 108 + "> 109 + <h1 lang="en">JavaScript Required</h1> 110 + <p lang="en">This is a heavily interactive web application, and JavaScript is required. Simple HTML interfaces are possible, but that is not what this is. 111 + <p lang="en">Learn more about Blacksky at <a href="https://blackskyweb.xyz">blackskyweb.xyz</a> and <a href="https://atproto.com">atproto.com</a>, or this fork at <a href="https://github.com/blacksky-algorithms/blacksky.community">github.com/blacksky-algorithms/blacksky.community</a>.</p> 112 + </noscript> 190 113 191 114 <!-- The root element for your Expo app. --> 192 - <div id="root"> 193 - <div id="splash"> 194 - <!-- Bluesky SVG --> 195 - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 57"><path fill="#006AFF" d="M13.873 3.805C21.21 9.332 29.103 20.537 32 26.55v15.882c0-.338-.13.044-.41.867-1.512 4.456-7.418 21.847-20.923 7.944-7.111-7.32-3.819-14.64 9.125-16.85-7.405 1.264-15.73-.825-18.014-9.015C1.12 23.022 0 8.51 0 6.55 0-3.268 8.579-.182 13.873 3.805ZM50.127 3.805C42.79 9.332 34.897 20.537 32 26.55v15.882c0-.338.13.044.41.867 1.512 4.456 7.418 21.847 20.923 7.944 7.111-7.32 3.819-14.64-9.125-16.85 7.405 1.264 15.73-.825 18.014-9.015C62.88 23.022 64 8.51 64 6.55c0-9.818-8.578-6.732-13.873-2.745Z"/></svg> 196 - </div> 115 + <div id="root"> 116 + <div id="splash"> 117 + <!-- Blacksky SVG scaled by parent width (100 px) --> 118 + <svg 119 + xmlns="http://www.w3.org/2000/svg" 120 + viewBox="0 0 285 243" 121 + preserveAspectRatio="xMidYMid meet" 122 + style="width:100%;height:auto;display:block" 123 + > 124 + <g clip-path="url(#clip0_1011_989)"> 125 + <path d="M148.846 144.562C148.846 159.75 161.158 172.062 176.346 172.062H207.012V185.865H176.346C161.158 185.865 148.846 198.177 148.846 213.365V243.045H136.029V213.365C136.029 198.177 123.717 185.865 108.529 185.865H77.8633V172.062H108.529C123.717 172.062 136.029 159.75 136.029 144.562V113.896H148.846V144.562Z" fill="currentColor"/> 126 + <path d="M170.946 31.8766C160.207 42.616 160.207 60.0281 170.946 70.7675L192.631 92.4516L182.871 102.212L161.186 80.5275C150.447 69.7881 133.035 69.7881 122.296 80.5275L101.309 101.514L92.2456 92.4509L113.232 71.4642C123.972 60.7248 123.972 43.3128 113.232 32.5733L91.5488 10.8899L101.309 1.12988L122.993 22.814C133.732 33.5533 151.144 33.5534 161.884 22.814L183.568 1.12988L192.631 10.1925L170.946 31.8766Z" fill="currentColor"/> 127 + <path d="M79.0525 75.3259C75.1216 89.9962 83.8276 105.076 98.498 109.006L128.119 116.943L124.547 130.275L94.9267 122.338C80.2564 118.407 65.1772 127.113 61.2463 141.784L53.5643 170.453L41.1837 167.136L48.8654 138.467C52.7963 123.797 44.0902 108.718 29.4199 104.787L-0.201172 96.8497L3.37124 83.5173L32.9923 91.4542C47.6626 95.3851 62.7419 86.679 66.6728 72.0088L74.6098 42.3877L86.9895 45.7048L79.0525 75.3259Z" fill="currentColor"/> 128 + <path d="M218.413 71.4229C222.344 86.093 237.423 94.7992 252.094 90.8683L281.715 82.9313L285.287 96.2628L255.666 104.2C240.995 108.131 232.29 123.21 236.22 137.88L243.902 166.55L231.522 169.867L223.841 141.198C219.91 126.528 204.831 117.822 190.16 121.753L160.539 129.69L156.967 116.357L186.588 108.42C201.258 104.49 209.964 89.4103 206.033 74.74L198.096 45.1189L210.476 41.8018L218.413 71.4229Z" fill="currentColor"/> 129 + </g> 130 + <defs> 131 + <clipPath id="clip0_1011_989"> 132 + <rect width="285" height="243" fill="white"/> 133 + </clipPath> 134 + </defs> 135 + </svg> 197 136 </div> 137 + </div> 198 138 </body> 199 139 </html>