@@ -120,13 +122,15 @@ const getCreateSomethingButtonName = computed(() => {
@@ -214,12 +218,14 @@ h1 {
padding-bottom: 6px;
}
-h1, .title h2 {
+h1,
+.title h2 {
padding-right: 4px;
padding-left: 4px;
}
-.title, .aside-box {
+.title,
+.aside-box {
box-shadow: 0px 1px #FFB6C1, 0px -1px #FFB6C1;
}
diff --git a/PinkSea.Frontend/src/models/search-type.ts b/PinkSea.Frontend/src/models/search-type.ts
new file mode 100644
index 0000000..86c4931
--- /dev/null
+++ b/PinkSea.Frontend/src/models/search-type.ts
@@ -0,0 +1,5 @@
+export enum SearchType {
+ Posts,
+ Profiles,
+ Tags
+}
diff --git a/PinkSea.Frontend/src/models/tag-search-result.ts b/PinkSea.Frontend/src/models/tag-search-result.ts
new file mode 100644
index 0000000..789f1c8
--- /dev/null
+++ b/PinkSea.Frontend/src/models/tag-search-result.ts
@@ -0,0 +1,7 @@
+import type { Oekaki } from '@/models/oekaki'
+
+export interface TagSearchResult {
+ tag: string,
+ oekaki: Oekaki,
+ count: number
+}
diff --git a/PinkSea.Frontend/src/router/index.ts b/PinkSea.Frontend/src/router/index.ts
index c35c585..561b486 100644
--- a/PinkSea.Frontend/src/router/index.ts
+++ b/PinkSea.Frontend/src/router/index.ts
@@ -10,6 +10,7 @@ import TagView from '@/views/TagView.vue'
import SettingsView from '@/views/SettingsView.vue'
import i18next from 'i18next'
import { withTegakiViewBackProtection } from '@/api/tegaki/tegaki-view-helper'
+import SearchView from '@/views/SearchView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
@@ -80,6 +81,16 @@ const router = createRouter({
return { name: 'breadcrumb.settings' };
}
}
+ },
+ {
+ path: '/search/:value',
+ name: 'search',
+ component: SearchView,
+ meta: {
+ resolveBreadcrumb: async (route: RouteParamsGeneric) => {
+ return { name: "breadcrumb.search", params: { value: route.value } };
+ }
+ }
}
]
});
diff --git a/PinkSea.Frontend/src/views/PostView.vue b/PinkSea.Frontend/src/views/PostView.vue
index 896a4b2..84a2f6f 100644
--- a/PinkSea.Frontend/src/views/PostView.vue
+++ b/PinkSea.Frontend/src/views/PostView.vue
@@ -9,8 +9,9 @@ import PostViewOekakiParentCard from '@/components/oekaki/PostViewOekakiParentCa
import PostViewOekakiChildCard from '@/components/oekaki/PostViewOekakiChildCard.vue'
import RespondBox from '@/components/RespondBox.vue'
import Loader from '@/components/Loader.vue'
-import PostViewOekakiTombstoneCard from '@/components/oekaki/PostViewOekakiTombstoneCard.vue'
+import PostViewOekakiTombstoneCard from '@/components/ErrorCard.vue'
import type { OekakiTombstone } from '@/models/oekaki-tombstone'
+import ErrorCard from '@/components/ErrorCard.vue'
const route = useRoute();
@@ -47,7 +48,7 @@ onBeforeMount(async () => {
-
+
diff --git a/PinkSea.Frontend/src/views/SearchView.vue b/PinkSea.Frontend/src/views/SearchView.vue
new file mode 100644
index 0000000..8445351
--- /dev/null
+++ b/PinkSea.Frontend/src/views/SearchView.vue
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t("timeline.nothing_here") }}
+
+
+
+
+
+
+
+
+ {{ $t("timeline.nothing_here") }}
+
+
+
+
+
+
+
diff --git a/PinkSea.Frontend/src/views/UserView.vue b/PinkSea.Frontend/src/views/UserView.vue
index f6e76d8..3223eff 100644
--- a/PinkSea.Frontend/src/views/UserView.vue
+++ b/PinkSea.Frontend/src/views/UserView.vue
@@ -6,6 +6,8 @@ import { computed, ref, watch } from 'vue'
import { xrpc } from '@/api/atproto/client'
import { useRoute } from 'vue-router'
import { UserProfileTab } from '@/models/user-profile-tab'
+import { XRPCError } from '@atcute/client'
+import ErrorCard from '@/components/ErrorCard.vue'
const tabs = [
{
@@ -21,11 +23,27 @@ const tabs = [
const handle = ref
("");
const route = useRoute();
+const exists = ref(null);
+const profileError = ref("");
+
const currentTab = ref(UserProfileTab.Posts);
watch(() => route.params.did, async () => {
- const { data } = await xrpc.get("com.shinolabs.pinksea.getHandleFromDid", { params: { did: route.params.did as string }});
- handle.value = data.handle;
+ try {
+ const { data } = await xrpc.get("com.shinolabs.pinksea.unspecced.getProfile", { params: { did: route.params.did as string }});
+ handle.value = data.handle;
+ exists.value = true;
+ } catch (e) {
+ if (e instanceof XRPCError) {
+ const xrpcError = e as XRPCError;
+ profileError.value = xrpcError.description ?? "An unknown error has occurred.";
+ } else {
+ profileError.value = "Failed to load the profile.";
+ }
+
+ exists.value = false;
+ }
+
}, { immediate: true });
const bskyUrl = computed(() => {
@@ -40,17 +58,25 @@ const domainUrl = computed(() => {
-
-
{{ $t("breadcrumb.user_profile", { handle: handle }) }}
-
-
+
+ loading...
+
+
+
+
{{ $t("breadcrumb.user_profile", { handle: handle }) }}
+
+
+
+
+
+
-