tangled
alpha
login
or
join now
flo-bit.dev
/
blento
your personal website on atproto - mirror
blento.app
20
fork
atom
overview
issues
pulls
pipelines
add latest bluesky post
Florian
1 month ago
afb7a815
397d86f4
+115
-15
13 changed files
expand all
collapse all
unified
split
src
lib
Profile.svelte
cards
BlueskyPostCard
BlueskyPostCard.svelte
BlueskyPostEditingCard.svelte
SidebarItemBlueskyPostCard.svelte
index.ts
SpecialCards
UpdatedBlentos
MainUpdatedBlentosCards.svelte
index.ts
helper.ts
website
utils.ts
routes
+page.svelte
[handle]
+page.svelte
edit
+page.svelte
edit
+page.svelte
+1
-1
src/lib/Profile.svelte
···
106
106
</div>
107
107
{/if}
108
108
{/if}
109
109
-
<div class="hidden text-xs font-light @5xl/wrapper:flex">
109
109
+
<div class="hidden text-xs font-light @5xl/wrapper:block">
110
110
made with <a
111
111
href="https://blento.app"
112
112
target="_blank"
+20
src/lib/cards/BlueskyPostCard/BlueskyPostCard.svelte
···
1
1
+
<script lang="ts">
2
2
+
import { getAdditionalUserData } from '$lib/helper';
3
3
+
import BaseCard, { type BaseCardProps } from '../BaseCard/BaseCard.svelte';
4
4
+
import { BlueskyPost } from '@foxui/social';
5
5
+
6
6
+
let { item, ...rest }: BaseCardProps = $props();
7
7
+
8
8
+
const feed = getAdditionalUserData().recentPosts?.feed;
9
9
+
10
10
+
$inspect(feed);
11
11
+
</script>
12
12
+
13
13
+
<BaseCard {item} {...rest}>
14
14
+
<div class="flex max-h-full overflow-y-scroll p-4">
15
15
+
{#if feed?.[0].post}
16
16
+
<BlueskyPost showLogo showReply={false} showBookmark={false} feedViewPost={feed?.[0].post}
17
17
+
></BlueskyPost>
18
18
+
{:else}{/if}
19
19
+
</div>
20
20
+
</BaseCard>
+20
src/lib/cards/BlueskyPostCard/BlueskyPostEditingCard.svelte
···
1
1
+
<script lang="ts">
2
2
+
import { getAdditionalUserData } from '$lib/helper';
3
3
+
import type { Item } from '$lib/types';
4
4
+
import BaseEditingCard, { type BaseEditingCardProps } from '../BaseCard/BaseEditingCard.svelte';
5
5
+
import { BlueskyPost } from '@foxui/social';
6
6
+
7
7
+
let { item = $bindable<Item>(), ...rest }: BaseEditingCardProps = $props();
8
8
+
const feed = getAdditionalUserData().recentPosts?.feed;
9
9
+
</script>
10
10
+
11
11
+
<BaseEditingCard {item} {...rest}>
12
12
+
<div class="flex max-h-full overflow-y-scroll p-4">
13
13
+
{#if feed?.[0].post}
14
14
+
<BlueskyPost showLogo showReply={false} showBookmark={false} feedViewPost={feed?.[0].post}
15
15
+
></BlueskyPost>
16
16
+
{:else}
17
17
+
Your latest bluesky post will appear here.
18
18
+
{/if}
19
19
+
</div>
20
20
+
</BaseEditingCard>
+15
src/lib/cards/BlueskyPostCard/SidebarItemBlueskyPostCard.svelte
···
1
1
+
<script lang="ts">
2
2
+
import { Button } from '@foxui/core';
3
3
+
4
4
+
let { onclick }: { onclick: () => void } = $props();
5
5
+
</script>
6
6
+
7
7
+
<Button {onclick} variant="ghost" class="w-full" size="lg">
8
8
+
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" class="size-4" viewBox="0 0 600 530">
9
9
+
<path
10
10
+
d="m135.72 44.03c66.496 49.921 138.02 151.14 164.28 205.46 26.262-54.316 97.782-155.54 164.28-205.46 47.98-36.021 125.72-63.892 125.72 24.795 0 17.712-10.155 148.79-16.111 170.07-20.703 73.984-96.144 92.854-163.25 81.433 117.3 19.964 147.14 86.092 82.697 152.22-122.39 125.59-175.91-31.511-189.63-71.766-2.514-7.3797-3.6904-10.832-3.7077-7.8964-0.0174-2.9357-1.1937 0.51669-3.7077 7.8964-13.714 40.255-67.233 197.36-189.63 71.766-64.444-66.128-34.605-132.26 82.697-152.22-67.108 11.421-142.55-7.4491-163.25-81.433-5.9562-21.282-16.111-152.36-16.111-170.07 0-88.687 77.742-60.816 125.72-24.795z"
11
11
+
fill="currentColor"
12
12
+
/>
13
13
+
</svg>
14
14
+
Latest Bluesky Post
15
15
+
</Button>
+14
src/lib/cards/BlueskyPostCard/index.ts
···
1
1
+
import type { CardDefinition } from '../types';
2
2
+
import BlueskyPostEditingCard from './BlueskyPostEditingCard.svelte';
3
3
+
import BlueskyPostCard from './BlueskyPostCard.svelte';
4
4
+
import SidebarItemBlueskyPostCard from './SidebarItemBlueskyPostCard.svelte';
5
5
+
6
6
+
export const BlueskyPostCardDefinition = {
7
7
+
type: 'latestPost',
8
8
+
cardComponent: BlueskyPostCard,
9
9
+
editingCardComponent: BlueskyPostEditingCard,
10
10
+
createNew: (card) => {
11
11
+
card.cardType = 'latestPost';
12
12
+
},
13
13
+
sidebarComponent: SidebarItemBlueskyPostCard
14
14
+
} as CardDefinition & { type: 'latestPost' };
+2
-2
src/lib/cards/SpecialCards/UpdatedBlentos/MainUpdatedBlentosCards.svelte
···
1
1
<script lang="ts">
2
2
-
import { getRecentRecords } from '$lib/helper';
2
2
+
import { getAdditionalUserData } from '$lib/helper';
3
3
import { getProfile } from '$lib/oauth/atproto';
4
4
import type { ProfileViewDetailed } from '@atproto/api/dist/client/types/app/bsky/actor/defs';
5
5
import { onMount } from 'svelte';
6
6
7
7
-
const recentRecords = getRecentRecords();
7
7
+
const recentRecords = getAdditionalUserData().recentRecords;
8
8
9
9
let profiles: ProfileViewDetailed[] = $state([]);
10
10
+3
-1
src/lib/cards/index.ts
···
1
1
+
import { BlueskyPostCardDefinition } from './BlueskyPostCard';
1
2
import { ImageCardDefinition } from './ImageCard';
2
3
import { LinkCardDefinition } from './LinkCard';
3
4
import { UpdatedBlentosCardDefitition } from './SpecialCards/UpdatedBlentos';
···
10
11
TextCardDefinition,
11
12
LinkCardDefinition,
12
13
UpdatedBlentosCardDefitition,
13
13
-
YoutubeCardDefinition
14
14
+
YoutubeCardDefinition,
15
15
+
BlueskyPostCardDefinition
14
16
] as const;
15
17
16
18
export const CardDefinitionsByType = AllCardDefinitions.reduce(
+1
-1
src/lib/helper.ts
···
147
147
148
148
export const [getCanEdit, setCanEdit] = createContext<() => boolean>();
149
149
150
150
-
export const [getRecentRecords, setRecentRecords] = createContext();
150
150
+
export const [getAdditionalUserData, setAdditionalUserData] = createContext();
+31
-2
src/lib/website/utils.ts
···
8
8
import type { Record as ListRecord } from '@atproto/api/dist/client/types/com/atproto/repo/listRecords';
9
9
import { data } from './data';
10
10
import { client } from '$lib/oauth';
11
11
+
import { AtpBaseClient } from '@atproto/api';
11
12
12
13
export function parseUri(uri: string) {
13
14
const [did, collection, rkey] = uri.split('/').slice(2);
···
69
70
}
70
71
}
71
72
73
73
+
const cardTypes = new Set(
74
74
+
Object.values(downloadedData['app.blento.card']).map((v) => v.value.cardType)
75
75
+
);
76
76
+
72
77
let recentRecords;
73
73
-
if (handle === 'blento.app') {
78
78
+
if (cardTypes.has('updatedBlentos')) {
74
79
try {
75
80
// https://ufos-api.microcosm.blue/records?collection=app.blento.card
76
81
const response = await fetch(
···
82
87
}
83
88
}
84
89
85
85
-
return { did, data: JSON.parse(JSON.stringify(downloadedData)) as DownloadedData, recentRecords };
90
90
+
let recentPosts;
91
91
+
92
92
+
if (cardTypes.has('latestPost')) {
93
93
+
try {
94
94
+
const agent = new AtpBaseClient({ service: 'https://api.bsky.app' });
95
95
+
const authorFeed = await agent.app.bsky.feed.getAuthorFeed({
96
96
+
actor: did,
97
97
+
filter: 'posts_no_replies',
98
98
+
limit: 2
99
99
+
});
100
100
+
console.log(authorFeed.data);
101
101
+
recentPosts = JSON.parse(JSON.stringify(authorFeed.data));
102
102
+
} catch (error) {
103
103
+
console.error('failed to fetch recent posts', error);
104
104
+
}
105
105
+
}
106
106
+
107
107
+
return {
108
108
+
did,
109
109
+
data: JSON.parse(JSON.stringify(downloadedData)) as DownloadedData,
110
110
+
additionalData: {
111
111
+
recentRecords,
112
112
+
recentPosts
113
113
+
}
114
114
+
};
86
115
}
87
116
88
117
export async function uploadBlob(blob: Blob) {
+2
-2
src/routes/+page.svelte
···
1
1
<script lang="ts">
2
2
-
import { setRecentRecords } from '$lib/helper.js';
2
2
+
import { setAdditionalUserData } from '$lib/helper.js';
3
3
import { type Item } from '$lib/types.js';
4
4
import Website from '$lib/Website.svelte';
5
5
6
6
let { data } = $props();
7
7
8
8
// svelte-ignore state_referenced_locally
9
9
-
setRecentRecords(data.recentRecords);
9
9
+
setAdditionalUserData(data.additionalData);
10
10
</script>
11
11
12
12
<Website
+2
-2
src/routes/[handle]/+page.svelte
···
1
1
<script lang="ts">
2
2
import { page } from '$app/state';
3
3
-
import { setRecentRecords } from '$lib/helper.js';
3
3
+
import { setAdditionalUserData } from '$lib/helper.js';
4
4
import { type Item } from '$lib/types.js';
5
5
import Website from '$lib/Website.svelte';
6
6
7
7
let { data } = $props();
8
8
9
9
// svelte-ignore state_referenced_locally
10
10
-
setRecentRecords(data.recentRecords);
10
10
+
setAdditionalUserData(data.additionalData);
11
11
</script>
12
12
13
13
<Website
+2
-2
src/routes/[handle]/edit/+page.svelte
···
1
1
<script lang="ts">
2
2
import { page } from '$app/state';
3
3
import EditableWebsite from '$lib/EditableWebsite.svelte';
4
4
-
import { setRecentRecords } from '$lib/helper.js';
4
4
+
import { setAdditionalUserData } from '$lib/helper.js';
5
5
import { type Item } from '$lib/types.js';
6
6
7
7
let { data } = $props();
8
8
9
9
// svelte-ignore state_referenced_locally
10
10
-
setRecentRecords(data.recentRecords);
10
10
+
setAdditionalUserData(data.additionalData);
11
11
</script>
12
12
13
13
<EditableWebsite
+2
-2
src/routes/edit/+page.svelte
···
1
1
<script lang="ts">
2
2
import EditableWebsite from '$lib/EditableWebsite.svelte';
3
3
-
import { setRecentRecords } from '$lib/helper.js';
3
3
+
import { setAdditionalUserData } from '$lib/helper.js';
4
4
import { type Item } from '$lib/types.js';
5
5
6
6
let { data } = $props();
7
7
8
8
// svelte-ignore state_referenced_locally
9
9
-
setRecentRecords(data.recentRecords);
9
9
+
setAdditionalUserData(data.additionalData);
10
10
</script>
11
11
12
12
<EditableWebsite