Skip to content

Commit c012a45

Browse files
committed
fix merge, change likes cols to 2
1 parent 45d35ef commit c012a45

4 files changed

Lines changed: 54 additions & 56 deletions

File tree

app/components/Package/LikeCard.vue

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ const props = defineProps<{
55
packageUrl: string
66
}>()
77
8+
const compactNumberFormatter = useCompactNumberFormatter()
9+
810
function extractPackageFromRef(ref: string) {
911
const { pkg } = /https:\/\/npmx.dev\/package\/(?<pkg>.*)/.exec(ref).groups
1012
return pkg
@@ -72,7 +74,7 @@ const likeAction = async () => {
7274
<NuxtLink :to="packageRoute(name)">
7375
<BaseCard class="group font-mono flex justify-between">
7476
{{ name }}
75-
<div class="flex items-center gap-4">
77+
<div class="flex items-center gap-4 justify-between">
7678
<ClientOnly>
7779
<TooltipApp
7880
:text="likesData?.userHasLiked ? $t('package.likes.unlike') : $t('package.likes.like')"
@@ -98,11 +100,13 @@ const likeAction = async () => {
98100
class="w-4 h-4"
99101
aria-hidden="true"
100102
/>
101-
<span>{{ formatCompactNumber(likesData?.totalLikes ?? 0, { decimals: 1 }) }}</span>
103+
<span>{{
104+
compactNumberFormatter.format(likesData?.totalLikes ?? 0, { decimals: 1 })
105+
}}</span>
102106
</button>
103107
</TooltipApp>
104108
</ClientOnly>
105-
<p class="transition-transform duration-150 group-hover:rotate-45 pt-1">↗</p>
109+
<p class="transition-transform duration-150 group-hover:rotate-45 pb-1">↗</p>
106110
</div>
107111
</BaseCard>
108112
</NuxtLink>

app/pages/profile/[handle]/index.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,9 @@ defineOgImageComponent('Default', {
145145

146146
<!-- Display Profile -->
147147
<div v-else class="flex flex-col flex-wrap gap-4">
148-
<h1 class="font-mono text-2xl sm:text-3xl font-medium">{{ profile.displayName }}</h1>
148+
<h1 v-if="profile.displayName" class="font-mono text-2xl sm:text-3xl font-medium">
149+
{{ profile.displayName }}
150+
</h1>
149151
<p v-if="profile.description">{{ profile.description }}</p>
150152
<div class="flex gap-4 items-center font-mono text-sm">
151153
<h2>@{{ handle }}</h2>
@@ -184,7 +186,7 @@ defineOgImageComponent('Default', {
184186
<div v-else-if="status === 'error'">
185187
<p>Error</p>
186188
</div>
187-
<div v-else class="grid grid-cols-1 lg:grid-cols-3 gap-4">
189+
<div v-else-if="likesData.likes.records" class="grid grid-cols-1 lg:grid-cols-2 gap-4">
188190
<PackageLikeCard
189191
v-if="likesData.likes.records"
190192
v-for="like in likesData.likes.records"

server/api/auth/atproto.get.ts

Lines changed: 39 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import { UNSET_NUXT_SESSION_PASSWORD } from '#shared/utils/constants'
1515
// @ts-expect-error virtual file from oauth module
1616
import { clientUri } from '#oauth/config'
1717

18+
const OAUTH_REQUEST_COOKIE_PREFIX = 'atproto_oauth_req'
19+
1820
export default defineEventHandler(async event => {
1921
const config = useRuntimeConfig(event)
2022
if (!config.sessionPassword) {
@@ -81,8 +83,12 @@ export default defineEventHandler(async event => {
8183
try {
8284
const state = decodeOAuthState(event, result.state)
8385
const profile = await getMiniProfile(result.session)
86+
const npmxProfile = await getNpmxProfile(query.handle as string, result.session)
8487

85-
await session.update({ public: profile })
88+
await session.update({
89+
public: profile,
90+
profile: npmxProfile,
91+
})
8692
return sendRedirect(event, state.redirectPath)
8793
} catch (error) {
8894
// If we are unable to cleanly handle the callback, meaning that the
@@ -118,15 +124,6 @@ type OAuthStateData = {
118124
redirectPath: string
119125
}
120126

121-
const miniDocResponse = await fetch(
122-
`https://${SLINGSHOT_HOST}/xrpc/blue.microcosm.identity.resolveMiniDoc?identifier=${agent.did}`,
123-
{ headers: { 'User-Agent': 'npmx' } },
124-
)
125-
126-
if (miniDocResponse.ok) {
127-
const miniDoc: PublicUserSession = await miniDocResponse.json()
128-
const OAUTH_REQUEST_COOKIE_PREFIX = 'atproto_oauth_req'
129-
130127
/**
131128
* This function encodes the OAuth state by generating a random SID, storing it
132129
* in a cookie, and returning a JSON string containing the original state and
@@ -175,46 +172,6 @@ function generateRandomHexString(byteLength: number = 16): string {
175172
).join('')
176173
}
177174

178-
// get existing npmx profile OR create a new one
179-
const profileUri = `at://${agent.did}/dev.npmx.actor.profile/self`
180-
const profileResponse = await fetch(
181-
`https://${SLINGSHOT_HOST}/xrpc/blue.microcosm.repo.getRecordByUri?at_uri=${profileUri}`,
182-
{ headers: { 'User-Agent': 'npmx' } },
183-
)
184-
185-
if (profileResponse.ok) {
186-
const profile = await profileResponse.json()
187-
await session.update({
188-
public: {
189-
...miniDoc,
190-
avatar,
191-
},
192-
profile: profile.value,
193-
})
194-
} else {
195-
const profile = {
196-
website: '',
197-
displayName: miniDoc.handle,
198-
description: '',
199-
}
200-
201-
await agent.com.atproto.repo.createRecord({
202-
repo: miniDoc.handle,
203-
collection: 'dev.npmx.actor.profile',
204-
rkey: 'self',
205-
record: {
206-
$type: 'dev.npmx.actor.profile',
207-
...profile,
208-
},
209-
})
210-
211-
await session.update({
212-
public: {
213-
...miniDoc,
214-
avatar,
215-
},
216-
profile: profile,
217-
})
218175
/**
219176
* This function ensures that an oauth state was indeed encoded for the browser
220177
* session performing the oauth callback.
@@ -326,3 +283,35 @@ async function getAvatar(did: DidString, pds: string) {
326283
}
327284
return avatar
328285
}
286+
287+
async function getNpmxProfile(handle: string, authSession: OAuthSession) {
288+
const client = new Client(authSession)
289+
290+
// get existing npmx profile OR create a new one
291+
const profileUri = `at://${client.did}/dev.npmx.actor.profile/self`
292+
const profileResponse = await fetch(
293+
`https://${SLINGSHOT_HOST}/xrpc/blue.microcosm.repo.getRecordByUri?at_uri=${profileUri}`,
294+
{ headers: { 'User-Agent': 'npmx' } },
295+
)
296+
297+
if (profileResponse.ok) {
298+
const profile = await profileResponse.json()
299+
return profile
300+
} else {
301+
const profile = {
302+
website: '',
303+
displayName: handle,
304+
description: '',
305+
}
306+
307+
await client.createRecord(
308+
{
309+
$type: 'dev.npmx.actor.profile',
310+
...profile,
311+
},
312+
'self',
313+
)
314+
315+
return profile
316+
}
317+
}

server/utils/atproto/utils/likes.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ export class PackageLikesUtils {
290290
* @returns
291291
*/
292292
async getUserLikes(
293-
miniDoc: blue.microcosm.identity.resolveMiniDoc.OutputBody,
293+
miniDoc: blue.microcosm.identity.resolveMiniDoc.$OutputBody,
294294
limit: number = 10,
295295
) {
296296
const client = new Client(miniDoc.pds, {
@@ -300,7 +300,10 @@ export class PackageLikesUtils {
300300
limit,
301301
repo: miniDoc.did,
302302
})
303+
return result
304+
}
303305

306+
/*
304307
* Gets the likes evolution for a package as daily {day, likes} points.
305308
* Fetches ALL backlinks via paginated constellation calls, decodes TID
306309
* timestamps from each rkey, and groups by day.

0 commit comments

Comments
 (0)