Federation (#327)

* initial commit federation

* more federation

* more federation

* more federation

* completes follow, accept, undo

* add trail create activity

* process trail create activity

* more trail create activity

* adds missing endpoints

* adds update and delete activity

* adds comment activities

* adds activities back

* adds summit logs activities

* deletes follow counts table

* fixes migrations

* fixes migrations

* fixes migrations

* fixes migrations

* adds remote profiles

* ctd

* ctd

* we are getting closer...

* adds public summit logs

* fixes federated trails in lists

* adds remote lists

* adds list activites

* fixes lists

* adds notifications

* adds iri redirect

* fixes comments and summitlogs

* fixes follows and profiles

* adds asynchronous send

* fixes list search

* adds encryption key

* bug fixes

* fixes activity signing

* removes custon activity object types

* adds html editor

* fixes html editor

* fixes display issues on mastodon

* adds federated sharing

* finishes announcements

* fixes small summit log issues

* adds trail likes

* finalizes likes

* fixes images for komoot

* add disable federation option

* adds private profiles

* updates docs

* adds federated comments

* adds trail and comments actvitiypub routes

* adds mentions to editor

* adds mentions to trails, comments, summit logs

* updates theme

* updates theme

* update docs

* update docs

* updates docs

* fixes various frontend problems

* fixes activitypub follows api

* updates docs

* updates docs

---------

Co-authored-by: Christian Beutel <>
This commit is contained in:
Flomp
2025-06-21 10:09:22 +02:00
committed by GitHub
parent 742a6d9d30
commit 9276690d60
356 changed files with 57150 additions and 35470 deletions

View File

@@ -8,13 +8,16 @@
import CategoryCard from "$lib/components/category_card.svelte";
import Scene from "$lib/components/scene.svelte";
import TrailCard from "$lib/components/trail/trail_card.svelte";
import { defaultTrailSearchAttributes } from "$lib/models/trail.js";
import {
defaultTrailSearchAttributes,
type TrailSearchResult,
} from "$lib/models/trail.js";
import { categories } from "$lib/stores/category_store";
import {
searchActors,
searchMulti,
type ListSearchResult,
type LocationSearchResult,
type TrailSearchResult,
} from "$lib/stores/search_store.js";
import { theme } from "$lib/stores/theme_store";
import { currentUser } from "$lib/stores/user_store";
@@ -27,47 +30,58 @@
let searchDropdownItems: SearchItem[] = $state([]);
async function search(q: string) {
const r = await searchMulti({
queries: [
{
indexUid: "trails",
attributesToRetrieve: defaultTrailSearchAttributes,
q: q,
limit: 3,
},
{
indexUid: "lists",
q: q,
limit: 3,
},
{
indexUid: "locations",
q: q,
limit: 5,
},
],
});
if (q.startsWith("@")) {
const actors = await searchActors(q);
searchDropdownItems = actors.map((a) => ({
text: a.username,
description: `@${a.username}${a.isLocal ? "" : '@' + a.domain}`,
value: a,
icon:
a.icon ||
`https://api.dicebear.com/7.x/initials/svg?seed=${a.username}&backgroundType=gradientLinear`,
}));
} else {
const r = await searchMulti({
queries: [
{
indexUid: "trails",
attributesToRetrieve: defaultTrailSearchAttributes,
q: q,
limit: 3,
},
{
indexUid: "lists",
q: q,
limit: 3,
},
{
indexUid: "locations",
q: q,
limit: 5,
},
],
});
const trailItems = r[0].hits.map((t: TrailSearchResult) => ({
text: t.name,
description: `Trail ${t.location.length ? ", " + t.location : ""}`,
value: `@${t.author}${t.domain ? `@${t.domain}` : ""}/${t.id}`,
icon: "route",
}));
const listItems = r[1].hits.map((t: ListSearchResult) => ({
text: t.name,
description: `List, ${t.trails} ${$_("trail", { values: { n: t.trails } })}`,
value: t.id,
icon: "layer-group",
}));
const cityItems = r[2].hits.map((c: LocationSearchResult) => ({
text: c.name,
description: c.description,
value: c,
icon: getIconForLocation(c),
}));
const trailItems = r[0].hits.map((t: TrailSearchResult) => ({
text: t.name,
description: `Trail ${t.location.length ? ", " + t.location : ""}`,
value: t.id,
icon: "route",
}));
const listItems = r[1].hits.map((t: ListSearchResult) => ({
text: t.name,
description: `List, ${t.trails.length} ${$_("trail", { values: { n: t.trails.length } })}`,
value: t.id,
icon: "layer-group",
}));
const cityItems = r[2].hits.map((c: LocationSearchResult) => ({
text: c.name,
description: c.description,
value: c,
icon: getIconForLocation(c),
}));
searchDropdownItems = [...trailItems, ...listItems, ...cityItems];
searchDropdownItems = [...trailItems, ...listItems, ...cityItems];
}
}
function handleSearchClick(item: SearchItem) {
@@ -75,6 +89,10 @@
goto(`/trail/view/${item.value}`);
} else if (item.icon == "layer-group") {
goto(`/lists?list=${item.value}`);
} else if (item.value.username) {
goto(
`/profile/@${item.value.username}${item.value.isLocal ? "" : "@" + item.value.domain}`,
);
} else {
goto(`/map/?lat=${item.value.lat}&lon=${item.value.lon}`);
}
@@ -130,7 +148,12 @@
/>
{:else}
{#each data.trails as trail}
<a class="w-full md:max-w-72" href="/trail/view/{trail.id}">
<a
class="w-full md:max-w-72"
href="/trail/view/@{trail.author}{trail.domain
? '@' + trail.domain
: ''}/{trail.id}"
>
<TrailCard {trail} fullWidth></TrailCard></a
>
{/each}