diff --git a/app/components/account/AccountTabs.vue b/app/components/account/AccountTabs.vue index d8cc4d1981..8dd207bfcb 100644 --- a/app/components/account/AccountTabs.vue +++ b/app/components/account/AccountTabs.vue @@ -35,6 +35,15 @@ const tabs = computed(() => [ display: t('tab.media'), icon: 'i-ri:camera-2-line', }, + { + name: 'account-collections', + to: { + name: 'account-collections', + params: { server: server.value, account: account.value }, + }, + display: t('tab.collections'), + icon: 'i-ri:shapes-line', + }, ]) diff --git a/app/components/nav/NavBottom.vue b/app/components/nav/NavBottom.vue index 6cb34dcae0..2e02b963f1 100644 --- a/app/components/nav/NavBottom.vue +++ b/app/components/nav/NavBottom.vue @@ -4,6 +4,7 @@ import type { NavButtonName } from '../../composables/settings' import { NavButtonBookmark, + NavButtonCollection, NavButtonCompose, NavButtonExplore, NavButtonFavorite, @@ -39,6 +40,7 @@ const navButtons: NavButton[] = [ { name: 'local', component: NavButtonLocal }, { name: 'federated', component: NavButtonFederated }, { name: 'list', component: NavButtonList }, + { name: 'collection', component: NavButtonCollection }, { name: 'hashtag', component: NavButtonHashtag }, { name: 'moreMenu', component: NavButtonMoreMenu }, ] diff --git a/app/components/nav/NavSide.vue b/app/components/nav/NavSide.vue index 60d289b89c..81351195b5 100644 --- a/app/components/nav/NavSide.vue +++ b/app/components/nav/NavSide.vue @@ -65,6 +65,7 @@ const exploreLink = computed(() => { + + + diff --git a/app/components/settings/SettingsBottomNav.vue b/app/components/settings/SettingsBottomNav.vue index 8d545b74ad..af8e16ea92 100644 --- a/app/components/settings/SettingsBottomNav.vue +++ b/app/components/settings/SettingsBottomNav.vue @@ -21,6 +21,7 @@ const availableNavButtons: NavButton[] = [ { name: 'local', label: 'nav.local', icon: 'i-ri:group-2-line' }, { name: 'federated', label: 'nav.federated', icon: 'i-ri:earth-line' }, { name: 'list', label: 'nav.lists', icon: 'i-ri:list-check' }, + { name: 'collection', label: 'nav.collections', icon: 'i-ri:shapes-line' }, { name: 'hashtag', label: 'nav.hashtags', icon: 'i-ri:hashtag' }, { name: 'moreMenu', label: 'nav.more_menu', icon: 'i-ri:more-fill' }, ] as const diff --git a/app/composables/masto/routes.ts b/app/composables/masto/routes.ts index 31dfe4e806..40ae008b51 100644 --- a/app/composables/masto/routes.ts +++ b/app/composables/masto/routes.ts @@ -68,6 +68,26 @@ export function getStatusInReplyToRoute(status: mastodon.v1.Status) { }) } +export function getCollectionRoute(collection: mastodon.v1.Collection) { + return useRouter().resolve({ + name: 'collection', + params: { + server: currentServer.value, + id: collection.id, + }, + }) +} + +export function getAccountCollectionsRoute(account: mastodon.v1.Account) { + return useRouter().resolve({ + name: 'account-collections', + params: { + server: currentServer.value, + account: extractAccountHandle(account), + }, + }) +} + export function navigateToStatus({ status, focusReply = false }: { status: mastodon.v1.Status focusReply?: boolean diff --git a/app/composables/settings/definition.ts b/app/composables/settings/definition.ts index 8266b1a8e5..7350bf559f 100644 --- a/app/composables/settings/definition.ts +++ b/app/composables/settings/definition.ts @@ -7,7 +7,7 @@ export type OldFontSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' export type ColorMode = 'light' | 'dark' | 'system' -export type NavButtonName = 'home' | 'search' | 'notification' | 'mention' | 'favorite' | 'bookmark' | 'compose' | 'scheduledPosts' | 'explore' | 'local' | 'federated' | 'list' | 'hashtag' | 'setting' | 'moreMenu' +export type NavButtonName = 'home' | 'search' | 'notification' | 'mention' | 'favorite' | 'bookmark' | 'compose' | 'scheduledPosts' | 'explore' | 'local' | 'federated' | 'list' | 'collection' | 'hashtag' | 'setting' | 'moreMenu' export interface PreferencesSettings { hideAltIndicatorOnPosts: boolean diff --git a/app/pages/[[server]]/@[account]/index/collections.vue b/app/pages/[[server]]/@[account]/index/collections.vue new file mode 100644 index 0000000000..a5a23de0ff --- /dev/null +++ b/app/pages/[[server]]/@[account]/index/collections.vue @@ -0,0 +1,75 @@ + + + diff --git a/app/pages/[[server]]/collections.vue b/app/pages/[[server]]/collections.vue new file mode 100644 index 0000000000..7647938c44 --- /dev/null +++ b/app/pages/[[server]]/collections.vue @@ -0,0 +1,24 @@ + + + diff --git a/app/pages/[[server]]/collections/[id].vue b/app/pages/[[server]]/collections/[id].vue new file mode 100644 index 0000000000..e3492c68c5 --- /dev/null +++ b/app/pages/[[server]]/collections/[id].vue @@ -0,0 +1,106 @@ + + + diff --git a/app/pages/[[server]]/collections/index.vue b/app/pages/[[server]]/collections/index.vue new file mode 100644 index 0000000000..6b25bed724 --- /dev/null +++ b/app/pages/[[server]]/collections/index.vue @@ -0,0 +1,92 @@ + + + diff --git a/locales/en.json b/locales/en.json index 19c73da1f6..7082800238 100644 --- a/locales/en.json +++ b/locales/en.json @@ -99,6 +99,12 @@ "edit_title": "Description", "remove_label": "Remove attachment" }, + "collection": { + "created_by": "Created by", + "empty": "No accounts in this collection yet.", + "item_count": "{0} accounts|{0} account|{0} accounts", + "no_collections": "No collections yet." + }, "command": { "activate": "Activate", "complete": "Complete", @@ -192,6 +198,8 @@ }, "error": { "account_not_found": "Account {0} not found", + "collection_not_found": "Collection not found", + "collections_not_supported": "This server doesn't support collections.", "explore_list_empty": "Nothing is trending right now. Check back later!", "file_size_cannot_exceed_n_mb": "File size cannot exceed {0}MB", "quote_fetch_error": "Could not fetch the quoted post", @@ -320,6 +328,7 @@ "blocked_users": "Blocked users", "bookmarks": "Bookmarks", "built_at": "Built {0}", + "collections": "Collections", "compose": "Compose", "conversations": "Conversations", "docs": "Documentation", @@ -347,7 +356,9 @@ "zen_mode": "Zen Mode" }, "notification": { + "added_you_to_collection": "added you to a collection", "and": "and", + "collection_updated": "updated a collection you're in", "favourited_post": "favorited your post", "followed_you": "followed you", "followed_you_count": "{0} people followed you|{0} person followed you|{0} people followed you", @@ -695,10 +706,13 @@ }, "tab": { "accounts": "Accounts", + "collections": "Collections", "for_you": "For you", "hashtags": "Hashtags", + "in_collections": "Featuring you", "list": "List", "media": "Media", + "my_collections": "My collection", "news": "News", "notifications_admin": { "report": "Report", diff --git a/package.json b/package.json index ebe18fb123..94477659d5 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "iso-639-1": "^3.0.0", "lru-cache": "^11.0.0", "magic-string": "^0.30.19", - "masto": "^7.10.0", + "masto": "^7.12.0", "mocked-exports": "^0.1.1", "node-emoji": "^2.1.3", "nuxt": "^4.4.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a010229316..e6a181979b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -196,8 +196,8 @@ importers: specifier: ^0.30.19 version: 0.30.21 masto: - specifier: ^7.10.0 - version: 7.10.0 + specifier: ^7.12.0 + version: 7.12.0 mocked-exports: specifier: ^0.1.1 version: 0.1.1 @@ -8138,8 +8138,8 @@ packages: marky@1.3.0: resolution: {integrity: sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==} - masto@7.10.0: - resolution: {integrity: sha512-BTaivOeHkb87oND2Dp/QzRP5kWJnB5khH9xSsfS0N8WzEAziuKV4DjZAHdbh2SNemqwikQeYtMPBsl52Q9sreQ==} + masto@7.12.0: + resolution: {integrity: sha512-hSqRfaqVhtaRB3+lSJ4YusqBZ/tj4/gtzS0PXZgrg2JLiDFLmsBdmuyVVF2c+QlKSMEKo7grVh3dN8TX1TECVw==} math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} @@ -20200,7 +20200,7 @@ snapshots: marky@1.3.0: {} - masto@7.10.0: + masto@7.12.0: dependencies: change-case: 5.4.4 events-to-async: 2.0.2