chore: improve onboarding, app download links styling (#23134)

This commit is contained in:
Alex 2025-10-21 21:10:12 -05:00 committed by GitHub
parent 032de9ff2f
commit 76f5036026
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 82 additions and 93 deletions

View File

@ -474,6 +474,7 @@
"app_bar_signout_dialog_title": "Sign out", "app_bar_signout_dialog_title": "Sign out",
"app_download_links": "App Download Links", "app_download_links": "App Download Links",
"app_settings": "App Settings", "app_settings": "App Settings",
"app_stores": "App Stores",
"app_update_available": "App update is available", "app_update_available": "App update is available",
"appears_in": "Appears in", "appears_in": "Appears in",
"apply_count": "Apply ({count, number})", "apply_count": "Apply ({count, number})",
@ -745,6 +746,7 @@
"create": "Create", "create": "Create",
"create_album": "Create album", "create_album": "Create album",
"create_album_page_untitled": "Untitled", "create_album_page_untitled": "Untitled",
"create_api_key": "Create API key",
"create_library": "Create Library", "create_library": "Create Library",
"create_link": "Create link", "create_link": "Create link",
"create_link_to_share": "Create link to share", "create_link_to_share": "Create link to share",
@ -1351,7 +1353,7 @@
"minutes": "Minutes", "minutes": "Minutes",
"missing": "Missing", "missing": "Missing",
"mobile_app": "Mobile App", "mobile_app": "Mobile App",
"mobile_app_download_onboarding_note": "You can access these options again from the Utilities page.", "mobile_app_download_onboarding_note": "Download the companion mobile app using the following options",
"model": "Model", "model": "Model",
"month": "Month", "month": "Month",
"monthly_title_text_date_format": "MMMM y", "monthly_title_text_date_format": "MMMM y",
@ -1433,7 +1435,7 @@
"notifications_setting_description": "Manage notifications", "notifications_setting_description": "Manage notifications",
"oauth": "OAuth", "oauth": "OAuth",
"obtainium_configurator": "Obtainium Configurator", "obtainium_configurator": "Obtainium Configurator",
"obtainium_configurator_instructions": "Please create an API key and select a variant to create your Obtainium configuration link.", "obtainium_configurator_instructions": "Use Obtainium to install and update the Android app directly from Immich GitHub's release. Create an API key and select a variant to create your Obtainium configuration link",
"official_immich_resources": "Official Immich Resources", "official_immich_resources": "Official Immich Resources",
"offline": "Offline", "offline": "Offline",
"offset": "Offset", "offset": "Offset",

View File

@ -20,7 +20,7 @@
<AppShellHeader> <AppShellHeader>
<NavigationBar showUploadButton={false} noBorder /> <NavigationBar showUploadButton={false} noBorder />
</AppShellHeader> </AppShellHeader>
<AppShellSidebar bind:open={sidebarStore.isOpen}> <AppShellSidebar bind:open={sidebarStore.isOpen} class="border-none shadow-none">
<AdminSidebar /> <AdminSidebar />
</AppShellSidebar> </AppShellSidebar>

View File

@ -6,22 +6,26 @@
import { t } from 'svelte-i18n'; import { t } from 'svelte-i18n';
</script> </script>
<HStack wrap> <p>{$t('mobile_app_download_onboarding_note')}</p>
<HStack>
<Button <Button
size="large" size="medium"
shape="semi-round" shape="semi-round"
fullWidth
onclick={() => modalManager.show(AppDownloadModal, {})}
leadingIcon={mdiCellphoneArrowDownVariant}
>
{$t('app_stores')}
</Button>
<Button
size="medium"
shape="semi-round"
fullWidth
onclick={() => modalManager.show(ObtainiumConfigModal, {})} onclick={() => modalManager.show(ObtainiumConfigModal, {})}
leadingIcon={mdiLinkEdit} leadingIcon={mdiLinkEdit}
> >
{$t('obtainium_configurator')} {$t('obtainium_configurator')}
</Button> </Button>
<Button
size="large"
shape="semi-round"
onclick={() => modalManager.show(AppDownloadModal, {})}
leadingIcon={mdiCellphoneArrowDownVariant}
>
{$t('app_download_links')}
</Button>
</HStack> </HStack>
<p>{$t('mobile_app_download_onboarding_note')}</p>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { appStoreBadge, fdroidBadge, Modal, ModalBody, playStoreBadge } from '@immich/ui'; import { appStoreBadge, fdroidBadge, Modal, ModalBody, playStoreBadge, Text } from '@immich/ui';
import { t } from 'svelte-i18n'; import { t } from 'svelte-i18n';
interface Props { interface Props {
onClose: () => void; onClose: () => void;
@ -9,35 +9,29 @@
<Modal title={$t('app_download_links')} size="large" {onClose}> <Modal title={$t('app_download_links')} size="large" {onClose}>
<ModalBody> <ModalBody>
<div class="flex flex-col sm:grid sm:grid-cols-2 gap-5 text-immich-primary dark:text-immich-dark-primary"> <div class="sm:grid sm:grid-cols-2 gap-5">
<div> <div class="flex flex-col place-items-start">
<label class="font-medium text-immich-primary dark:text-immich-dark-primary text-sm" for="fdroid-link"> <Text>Google Play</Text>
F-Droid
</label>
<a href="https://f-droid.org/packages/app.alextran.immich/" target="_blank" id="fdroid-link">
<img class="pt-2 pr-10" alt="Get it on F-Droid" src={fdroidBadge} />
</a>
</div>
<div>
<label class="font-medium text-immich-primary dark:text-immich-dark-primary text-sm" for="play-store-link">
Google Play
</label>
<a <a
href="https://play.google.com/store/apps/details?id=app.alextran.immich" href="https://play.google.com/store/apps/details?id=app.alextran.immich"
target="_blank" target="_blank"
id="play-store-link" id="play-store-link"
> >
<img alt="Get it on Google Play" src={playStoreBadge} /> <img class="w-[200px] mt-2" alt="Get it on Google Play" src={playStoreBadge} />
</a> </a>
</div> </div>
<div> <div class="flex flex-col place-items-start">
<label class="font-medium text-immich-primary dark:text-immich-dark-primary text-sm" for="app-store-link"> <Text>App Store</Text>
App Store
</label>
<a href="https://apps.apple.com/us/app/immich/id1613945652" target="_blank" id="app-store-link"> <a href="https://apps.apple.com/us/app/immich/id1613945652" target="_blank" id="app-store-link">
<img class="pt-2 pr-5" alt="Download on the App Store" src={appStoreBadge} width="90%" /> <img class="w-[200px] mt-2" alt="Download on the App Store" src={appStoreBadge} />
</a>
</div>
<div class="flex flex-col place-items-start">
<Text>F-Droid</Text>
<a href="https://f-droid.org/packages/app.alextran.immich/" target="_blank" id="fdroid-link">
<img class="w-[200px] mt-2" alt="Get it on F-Droid" src={fdroidBadge} />
</a> </a>
</div> </div>
</div> </div>

View File

@ -4,7 +4,7 @@
import { SettingInputFieldType } from '$lib/constants'; import { SettingInputFieldType } from '$lib/constants';
import { handleError } from '$lib/utils/handle-error'; import { handleError } from '$lib/utils/handle-error';
import { createApiKey, Permission } from '@immich/sdk'; import { createApiKey, Permission } from '@immich/sdk';
import { Button, Modal, ModalBody, obtainiumBadge } from '@immich/ui'; import { Button, Modal, ModalBody, obtainiumBadge, Text } from '@immich/ui';
import { t } from 'svelte-i18n'; import { t } from 'svelte-i18n';
let inputUrl = $state(location.origin); let inputUrl = $state(location.origin);
let inputApiKey = $state(''); let inputApiKey = $state('');
@ -31,64 +31,53 @@
let { onClose }: Props = $props(); let { onClose }: Props = $props();
</script> </script>
<Modal title={$t('obtainium_configurator')} size="large" {onClose}> <Modal title={$t('obtainium_configurator')} size="medium" {onClose}>
<ModalBody> <ModalBody>
<div class="flex flex-col sm:grid sm:grid-cols-2 gap-5 text-immich-primary dark:text-immich-dark-primary"> <div>
<div> <Text color="muted" size="small">
<label {$t('obtainium_configurator_instructions')}
class="font-medium text-immich-primary dark:text-immich-dark-primary text-sm" </Text>
for="obtainium-configurator" <form class="mt-4">
> <div class="mt-2">
Obtainium <SettingInputField inputType={SettingInputFieldType.TEXT} label={$t('url')} bind:value={inputUrl} />
</label>
<div id="obtainium-configurator">
<form>
<div class="mt-2">
<SettingInputField inputType={SettingInputFieldType.TEXT} label={$t('url')} bind:value={inputUrl} />
</div>
<div class="mt-2">
<SettingInputField
inputType={SettingInputFieldType.TEXT}
label={$t('api_key')}
bind:value={inputApiKey}
/>
</div>
<div class="">
<Button shape="round" size="small" onclick={() => handleCreate()}>{$t('new_api_key')}</Button>
</div>
<div class="mt-2">
<SettingSelect
label={$t('app_architecture_variant')}
bind:value={archVariant}
options={[
{ value: 'arm64-v8a-release', text: 'arm64-v8a' },
{ value: 'armeabi-v7a-release', text: 'armeabi-v7a' },
{ value: 'release', text: 'universal' },
{ value: 'x86_64-release', text: 'x86_64' },
]}
/>
</div>
</form>
</div> </div>
</div>
<div class="content-center"> <div class="mt-2 flex gap-2 place-items-center place-content-center">
{#if inputUrl && inputApiKey && archVariant} <SettingInputField inputType={SettingInputFieldType.TEXT} label={$t('api_key')} bind:value={inputApiKey} />
<a
href={obtainiumLink} <div class="translate-y-[3px]">
class="underline text-sm immich-form-label" <Button size="small" onclick={() => handleCreate()}>{$t('create_api_key')}</Button>
target="_blank" </div>
rel="noreferrer" </div>
id="obtainium-link"
> <SettingSelect
<img class="pt-2 pr-5" alt="Get it on Obtainium" src={obtainiumBadge} /> label={$t('app_architecture_variant')}
</a> bind:value={archVariant}
{:else} options={[
<p class="immich-form-label pb-2 text-sm" id="obtainium-link"> { value: 'arm64-v8a-release', text: 'arm64-v8a' },
{$t('obtainium_configurator_instructions')} { value: 'armeabi-v7a-release', text: 'armeabi-v7a' },
</p> { value: 'release', text: 'universal' },
{/if} { value: 'x86_64-release', text: 'x86_64' },
</div> ]}
/>
</form>
{#if inputUrl && inputApiKey && archVariant}
<div class="content-center">
<hr />
<div class="flex place-items-center place-content-center">
<a
href={obtainiumLink}
class="underline text-sm immich-form-label"
target="_blank"
rel="noreferrer"
id="obtainium-link"
>
<img class="pt-2 pr-5 h-[80px]" alt="Get it on Obtainium" src={obtainiumBadge} />
</a>
</div>
</div>
{/if}
</div> </div>
</ModalBody> </ModalBody>
</Modal> </Modal>

View File

@ -90,7 +90,7 @@
component: OnboardingMobileApp, component: OnboardingMobileApp,
role: OnboardingRole.USER, role: OnboardingRole.USER,
title: $t('mobile_app'), title: $t('mobile_app'),
icon: mdiCellphoneArrowDownVariant, // or you can use mdiCellphone icon: mdiCellphoneArrowDownVariant,
}, },
]); ]);
@ -167,7 +167,7 @@
style="width: {(onboardingProgress / onboardingStepCount) * 100}%" style="width: {(onboardingProgress / onboardingStepCount) * 100}%"
></div> ></div>
</div> </div>
<div class="py-8 flex place-content-center place-items-center m-auto"> <div class="py-8 flex place-content-center place-items-center m-auto w-[min(100%,_800px)]">
<OnboardingCard <OnboardingCard
title={onboardingSteps[index].title} title={onboardingSteps[index].title}
icon={onboardingSteps[index].icon} icon={onboardingSteps[index].icon}