Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions packages/ui/src/modules/app-store/app-page/dependencies.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {arrayIncludes} from 'ts-extras'
import {AppIcon} from '@/components/app-icon'
import {Loading} from '@/components/ui/loading'
import {cn} from '@/lib/utils'
import {getAppStoreLink} from '@/modules/app-store/utils'
import {useApps} from '@/providers/apps'
import {useAllAvailableApps} from '@/providers/available-apps'
import {installedStates, RegistryApp} from '@/trpc/trpc'
Expand Down Expand Up @@ -69,13 +70,14 @@ const Dependency = ({
showDependencies?: (dependencyId?: string) => void
}) => {
const {t} = useTranslation()
const storeLink = getAppStoreLink(app)
return (
<div className='flex w-full items-center gap-2.5 pl-2'>
<Link to={`/app-store/${app.id}`} state={{fromAppStore: true}}>
<Link to={storeLink} state={{fromAppStore: true}}>
<AppIcon src={app.icon} size={36} className='rounded-8' />
</Link>
<div className='flex-col gap-4'>
<Link to={`/app-store/${app.id}`} state={{fromAppStore: true}} className='flex gap-1.5'>
<Link to={storeLink} state={{fromAppStore: true}} className='flex gap-1.5'>
<h3 className='truncate text-14 leading-tight font-semibold -tracking-3'>{app.name}</h3>
{installed && <TbCircleCheckFilled className='h-[16px] w-[16px] text-slate-500' />}
</Link>
Expand Down
21 changes: 18 additions & 3 deletions packages/ui/src/modules/app-store/select-dependencies-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
} from '@/components/ui/dropdown-menu'
import {ScrollArea} from '@/components/ui/scroll-area'
import {cn} from '@/lib/utils'
import {getAppStoreLink} from '@/modules/app-store/utils'
import {useApps} from '@/providers/apps'
import {useAllAvailableApps} from '@/providers/available-apps'
import {AppState, installedStates, RegistryApp} from '@/trpc/trpc'
Expand Down Expand Up @@ -184,6 +185,7 @@ export function SelectDependencies({
</span>
<DependencyStateText
appId={app.id}
app={app}
appState={userAppsKeyed?.[app.id]?.state ?? 'not-installed'}
onClick={onInstallClick}
/>
Expand All @@ -205,6 +207,7 @@ export function SelectDependencies({
/>
<DependencyStateText
appId={selectedDependencies[dependencyId]}
app={appsKeyed[selectedDependencies[dependencyId]]}
appState={userAppsKeyed?.[selectedDependencies[dependencyId]]?.state ?? 'not-installed'}
onClick={onInstallClick}
/>
Expand All @@ -219,7 +222,17 @@ const listClass = tw`divide-y divide-white/6 overflow-hidden rounded-12 bg-white
const listItemClass = tw`flex items-center pl-3 pr-4 h-[50px] text-[14px] font-medium -tracking-3 justify-between`
const listItemClassWithDropdown = tw`flex items-center pl-3 pr-4 h-[60px] text-[14px] font-medium -tracking-3 justify-between`

function DependencyStateText({appId, appState, onClick}: {appId: string; appState: AppState; onClick?: () => void}) {
function DependencyStateText({
appId,
app,
appState,
onClick,
}: {
appId: string
app?: RegistryApp
appState: AppState
onClick?: () => void
}) {
const {t} = useTranslation()
const buttonClass = 'w-[70px]' // Fixed width for both buttons

Expand All @@ -233,9 +246,11 @@ function DependencyStateText({appId, appState, onClick}: {appId: string; appStat

if (appState === 'not-installed') {
return (
// TODO: link to community app store if needed using `getAppStoreAppFromInstalledApp`
<ButtonLink
to={`/app-store/${appId}`}
// Fall back to the official app store route if the app is no longer
// present in any store, for example because a community app store
// has been removed
to={app ? getAppStoreLink(app) : `/app-store/${appId}`}
state={{fromAppStore: true}}
onClick={onClick}
variant='primary'
Expand Down
11 changes: 10 additions & 1 deletion packages/ui/src/modules/app-store/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {RegistryApp} from '@/trpc/trpc'
import {preloadImage} from '@/utils/misc'

import {categoryDescriptionsKeyed, categoryishDescriptions, type Categoryish} from './constants'
import {categoryDescriptionsKeyed, categoryishDescriptions, UMBREL_APP_STORE_ID, type Categoryish} from './constants'

const alreadyPreloadedFirstFewGalleryImages = new Set<string>()

Expand All @@ -11,6 +11,15 @@ export function preloadFirstFewGalleryImages(app: RegistryApp) {
app.gallery.slice(0, 3).map(preloadImage)
}

// Returns the store page path for an app, linking community store apps to
// their community app store instead of the official Umbrel App Store
export function getAppStoreLink(app: Pick<RegistryApp, 'id' | 'appStoreId'>): string {
if (app.appStoreId && app.appStoreId !== UMBREL_APP_STORE_ID) {
return `/community-app-store/${app.appStoreId}/${app.id}`
}
return `/app-store/${app.id}`
}

export function getCategoryLabel(categoryId: string): string {
const predefined = categoryDescriptionsKeyed[categoryId as Categoryish]

Expand Down