diff --git a/.prettierrc.json b/.prettierrc.json --- a/.prettierrc.json +++ b/.prettierrc.json @@ -2,5 +2,6 @@ "$schema": "https://json.schemastore.org/prettierrc", "semi": false, "singleQuote": true, - "printWidth": 100 + "printWidth": 100, + "useTabs": true } diff --git a/README.md b/README.md --- a/README.md +++ b/README.md @@ -1,1 +1,1 @@ -# scilla +# bluebell diff --git a/bun.lock b/bun.lock --- a/bun.lock +++ b/bun.lock @@ -2,7 +2,7 @@ "lockfileVersion": 1, "workspaces": { "": { - "name": "scilla", + "name": "bluebell", "dependencies": { "@atcute/atproto": "^3.1.9", "@atcute/bluesky": "^3.2.14", diff --git a/index.html b/index.html --- a/index.html +++ b/index.html @@ -1,13 +1,13 @@ - - - - - Scilla - - -
- - + + + + + Bluebell + + +
+ + diff --git a/package.json b/package.json --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "scilla", + "name": "bluebell", "version": "0.0.0", "private": true, "type": "module", diff --git a/public/bluebell.svg b/public/bluebell.svg new file mode 100644 --- /dev/null +++ b/public/bluebell.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/public/oauth-client-metadata.json b/public/oauth-client-metadata.json --- a/public/oauth-client-metadata.json +++ b/public/oauth-client-metadata.json @@ -1,13 +1,13 @@ { - "client_id": "http://localhost:5173/oauth-client-metadata.json", - "client_name": "Scilla", - "client_uri": "http://localhost:5173", - "logo_uri": "http://localhost:5173/favicon.ico", - "redirect_uris": ["http://localhost:5173/oauth/callback"], - "scope": "atproto transition:generic", - "grant_types": ["authorization_code", "refresh_token"], - "response_types": ["code"], - "token_endpoint_auth_method": "none", - "application_type": "web", - "dpop_bound_access_tokens": true + "client_id": "http://localhost:5173/oauth-client-metadata.json", + "client_name": "Bluebell", + "client_uri": "http://localhost:5173", + "logo_uri": "http://localhost:5173/favicon.ico", + "redirect_uris": ["http://localhost:5173/oauth/callback"], + "scope": "atproto transition:generic", + "grant_types": ["authorization_code", "refresh_token"], + "response_types": ["code"], + "token_endpoint_auth_method": "none", + "application_type": "web", + "dpop_bound_access_tokens": true } diff --git a/public/scilla.svg b/public/scilla.svg deleted file mode 100644 --- a/public/scilla.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/App.vue b/src/App.vue --- a/src/App.vue +++ b/src/App.vue @@ -8,6 +8,7 @@ import TabStack from '@/components/Navigation/TabStack.vue' import NavigationBar from '@/components/Navigation/NavigationBar.vue' import OAuthCallback from '@/views/Auth/OAuthCallback.vue' +import OnboardingFlow from '@/views/Onboarding/OnboardingFlow.vue' import { stackRoots, type StackRootNames } from './router' @@ -20,51 +21,78 @@ const tabs: StackRootNames[] = stackRoots.map((p) => p.name) const isCallback = ref(window.location.pathname.includes('/oauth/callback')) + +const hasSeenIntro = localStorage.getItem('bluebell-intro-complete') === 'true' +const showIntro = ref(!hasSeenIntro && !isCallback.value) + auth.init() + const onAuthComplete = () => { window.history.replaceState(null, '', '/') - theme.init() env.init() auth.init() isCallback.value = false } +const onIntroComplete = (action: 'stay' | 'login') => { + localStorage.setItem('bluebell-intro-complete', 'false') + showIntro.value = false + nav.init() + + if (action === 'login') { + setTimeout(() => { + nav.push('login') + }, 100) + } +} + onMounted(async () => { theme.init() env.init() - if (!isCallback.value) { + if (!showIntro.value && !isCallback.value) { nav.init() } }) diff --git a/src/views/Auth/LoginPage.vue b/src/views/Auth/LoginPage.vue --- a/src/views/Auth/LoginPage.vue +++ b/src/views/Auth/LoginPage.vue @@ -1,11 +1,11 @@ diff --git a/src/views/Auth/OAuthCallback.vue b/src/views/Auth/OAuthCallback.vue --- a/src/views/Auth/OAuthCallback.vue +++ b/src/views/Auth/OAuthCallback.vue @@ -2,11 +2,11 @@ import { onMounted, ref, computed } from 'vue' import { useAuthStore } from '@/stores/auth' import SVG from '@/components/UI/SVG.vue' -import ScillaLogo from '@/assets/icons/scilla.svg?raw' +import BluebellLogo from '@/assets/icons/bluebell.svg?raw' import { IconArrowForwardRounded } from '@iconify-prerendered/vue-material-symbols' import Button from '@/components/UI/BaseButton.vue' const emit = defineEmits<{ - (e: 'complete'): void + (e: 'complete'): void }>() const auth = useAuthStore() @@ -21,348 +21,348 @@ const loadingBar = ref(null) const displayName = computed(() => { - if (!profile.value) return '' - return profile.value.displayName || profile.value.handle + if (!profile.value) return '' + return profile.value.displayName || profile.value.handle }) const bannerUrl = computed(() => profile.value?.banner) const avatarUrl = computed(() => profile.value?.avatar) const proceed = async () => { - isExiting.value = true - await new Promise((r) => setTimeout(r, 600)) - emit('complete') + isExiting.value = true + await new Promise((r) => setTimeout(r, 600)) + emit('complete') } onMounted(async () => { - try { - const style = loadingBar.value?.style + try { + const style = loadingBar.value?.style - loadingMessage.value = 'verifying... ' - style?.setProperty('--scale', 1 / 3) + loadingMessage.value = 'verifying... ' + style?.setProperty('--scale', 1 / 3) - const success = await auth.handleCallback() - if (!success && !auth.isAuthenticated) throw new Error('Auth failed') + const success = await auth.handleCallback() + if (!success && !auth.isAuthenticated) throw new Error('Auth failed') - loadingMessage.value = 'finding you...' - style?.setProperty('--scale', 2 / 3) + loadingMessage.value = 'finding you...' + style?.setProperty('--scale', 2 / 3) - const rpc = auth.getRpc() - const { data } = await rpc.get('app.bsky.actor.getProfile', { - params: { actor: auth.session?.info.sub }, - }) + const rpc = auth.getRpc() + const { data } = await rpc.get('app.bsky.actor.getProfile', { + params: { actor: auth.session?.info.sub }, + }) - if (data.banner) { - const img = new Image() - img.src = data.banner - } + if (data.banner) { + const img = new Image() + img.src = data.banner + } - profile.value = data - loadingMessage.value = "nothing's happening this is just a spacer" - style?.setProperty('--scale', '1') + profile.value = data + loadingMessage.value = "nothing's happening this is just a spacer" + style?.setProperty('--scale', '1') - await new Promise((r) => setTimeout(r, 750)) - state.value = 'success' - } catch (e: any) { - console.error(e) - state.value = 'error' - errorMsg.value = e.message || 'Something went wrong' - setTimeout(() => (window.location.href = '/login'), 3000) - } + await new Promise((r) => setTimeout(r, 750)) + state.value = 'success' + } catch (e: any) { + console.error(e) + state.value = 'error' + errorMsg.value = e.message || 'Something went wrong' + setTimeout(() => (window.location.href = '/login'), 3000) + } }) diff --git a/src/views/Onboarding/OnboardingFlow.vue b/src/views/Onboarding/OnboardingFlow.vue new file mode 100644 --- /dev/null +++ b/src/views/Onboarding/OnboardingFlow.vue @@ -0,0 +1,163 @@ + + + + + diff --git a/src/views/Onboarding/steps/AuthStep.vue b/src/views/Onboarding/steps/AuthStep.vue new file mode 100644 --- /dev/null +++ b/src/views/Onboarding/steps/AuthStep.vue @@ -0,0 +1,73 @@ + + + + + diff --git a/src/views/Onboarding/steps/IntroStep.vue b/src/views/Onboarding/steps/IntroStep.vue new file mode 100644 --- /dev/null +++ b/src/views/Onboarding/steps/IntroStep.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/src/views/Onboarding/steps/ThemeStep.vue b/src/views/Onboarding/steps/ThemeStep.vue new file mode 100644 --- /dev/null +++ b/src/views/Onboarding/steps/ThemeStep.vue @@ -0,0 +1,147 @@ + + + + +