Skip to content

Commit ef0e1a8

Browse files
authored
feat(web): license UI (#11182)
1 parent 88f6208 commit ef0e1a8

39 files changed

+1157
-148
lines changed

.dockerignore

+1
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,4 @@ web/node_modules/
2929
web/coverage/
3030
web/.svelte-kit
3131
web/build/
32+
web/.env

docs/blog/2024/immich-core-team-goes-fulltime.mdx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: The Immich core team goes full-time
33
authors: [alextran]
4-
tags: [update, announcement, futo]
4+
tags: [update, announcement, FUTO]
55
date: 2024-05-01T00:00
66
---
77

docs/blog/2024/immich-licensing.mdx

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
---
2+
title: Licensing announcement - Purchase a license to support Immich
3+
authors: [alextran]
4+
tags: [update, announcement, FUTO]
5+
date: 2024-07-18T00:00
6+
---
7+
8+
Hello everybody,
9+
10+
Firstly, on behalf of the Immich team, I'd like to thank everybody for your continuous support of Immich since the very first day! Your contributions, encouragement, and community engagement have helped bring Immich to its current state. The team and I are forever grateful for that.
11+
12+
Since our [last announcement of the core team joining FUTO to work on Immich full-time](https://immich.app/blog/2024/immich-core-team-goes-fulltime), one of the goals of our new position is to foster a healthy relationship between the developers and the users. We believe that this enables us to create great software, establish transparent policies and build trust.
13+
14+
We want to build a great software application that brings value to you and your loved ones' lives. We are not using you as a product, i.e., selling or tracking your data. We are not putting annoying ads into our software. We respect your privacy. We want to be compensated for the hard work we put in to build Immich for you.
15+
16+
With those notes, we have enabled a way for you to financially support the continued development of Immich, ensuring the software can move forward and will be maintained, by offering a lifetime license of the software. We think if you like and use software, you should pay for it, but _we're never going to force anyone to pay or try to limit Immich for those who don't._
17+
18+
There are two types of license that you can choose to purchase: **Server License** and **Individual License**.
19+
20+
### Server License
21+
22+
This is a lifetime license costing **$99.99**. The license is applied to the whole server. You and all users that use your server are licensed.
23+
24+
### Individual License
25+
26+
This is a lifetime license costing **$24.99**. The license is applied to a single user, and can be used on any server they choose to connect to.
27+
28+
<img
29+
width="837"
30+
alt="license-social-gh"
31+
src="https://github.com/user-attachments/assets/241932ed-ef3b-44ec-a9e2-ee80754e0cca"
32+
/>
33+
34+
You can purchase the license on [our page - https://buy.immich.app](https://buy.immich.app).
35+
36+
Starting with release `v1.109.0` you can purchase and enter your purchased license key directly in the app.
37+
38+
<img
39+
width="1414"
40+
alt="license-page-gh"
41+
src="https://github.com/user-attachments/assets/364fc32a-f6ef-4594-9fea-28d5a26ad77c"
42+
/>
43+
44+
## Thank you
45+
46+
Thank you again for your support, this will help create a strong foundation and stability for the Immich team to continue developing and maintaining the project that you love to use.
47+
48+
<p align="center">
49+
<img
50+
src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExbjY2eWc5Y2F0ZW56MmR4aWE0dDhzZXlidXRmYWZyajl1bWZidXZpcyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/87CKDqErVfMqY/giphy.gif"
51+
width="550"
52+
title="SUPPORT THE PROJECT!"
53+
/>
54+
</p>
55+
56+
<br />
57+
<br />
58+
59+
Cheers! 🎉
60+
61+
Immich team
62+
63+
# FAQ
64+
65+
### 1. Where can I purchase a license?
66+
67+
There are several places where you can purchase the license from
68+
69+
- [https://buy.immich.app](https://buy.immich.app)
70+
- [https://pay.futo.org](https://pay.futo.org/)
71+
- or directly from the app.
72+
73+
### 2. Do I need both _Individual License_ and _Server License_?
74+
75+
No,
76+
77+
If you are the admin and the sole user, or your instance has less than a total of 4 users, you can buy the **Individual License** for each user.
78+
79+
If your instance has more than 4 users, it is more cost-effective to buy the **Server License**, which will license all the users on your instance.
80+
81+
### 3. What do I do if I don't pay?
82+
83+
You can continue using Immich for an unlimited trial period.
84+
85+
### 4. Will there be any paywalled features?
86+
87+
No, there will never be any paywalled features.
88+
89+
### 5. Where can I get support regarding payment issues?
90+
91+
You can email us with your `orderId` and your email address `[email protected]` or on our Discord server.

e2e/package-lock.json

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

e2e/src/api/specs/asset.e2e-spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ describe('/asset', () => {
507507
expect(status).toEqual(200);
508508
});
509509

510-
it('should geocode country from gps data in the middle of nowhere', async () => {
510+
it.skip('should geocode country from gps data in the middle of nowhere', async () => {
511511
const { status } = await request(app)
512512
.put(`/assets/${user1Assets[0].id}`)
513513
.set('Authorization', `Bearer ${user1.accessToken}`)

server/src/controllers/server.controller.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ export class ServerController {
9595

9696
@Get('license')
9797
@Authenticated({ admin: true })
98-
getServerLicense(): Promise<LicenseKeyDto | null> {
98+
getServerLicense(): Promise<LicenseResponseDto | null> {
9999
return this.service.getLicense();
100100
}
101101
}

server/src/emails/license.email.tsx

+186
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
import {
2+
Body,
3+
Button,
4+
Column,
5+
Container,
6+
Head,
7+
Hr,
8+
Html,
9+
Img,
10+
Link,
11+
Preview,
12+
Row,
13+
Section,
14+
Text,
15+
} from '@react-email/components';
16+
import * as CSS from 'csstype';
17+
import * as React from 'react';
18+
19+
/**
20+
* Template to be used for FUTOPay project
21+
* Variable is {{LICENSEKEY}}
22+
* */
23+
export const LicenseEmail = () => (
24+
<Html>
25+
<Head />
26+
<Preview>Your Immich Server License</Preview>
27+
<Body
28+
style={{
29+
margin: 0,
30+
padding: 0,
31+
backgroundColor: '#f4f4f4',
32+
color: 'rgb(28,28,28)',
33+
fontFamily: 'Overpass, sans-serif',
34+
fontSize: '18px',
35+
lineHeight: '24px',
36+
}}
37+
>
38+
<Container
39+
style={{
40+
width: '540px',
41+
maxWidth: '100%',
42+
padding: '10px',
43+
margin: '0 auto',
44+
}}
45+
>
46+
<Section
47+
style={{
48+
padding: '36px',
49+
tableLayout: 'fixed',
50+
backgroundColor: '#fefefe',
51+
borderRadius: '16px',
52+
textAlign: 'center' as const,
53+
}}
54+
>
55+
<Img
56+
src="https://immich.app/img/immich-logo-inline-light.png"
57+
alt="Immich"
58+
style={{
59+
height: 'auto',
60+
margin: '0 auto 48px auto',
61+
width: '50%',
62+
alignSelf: 'center',
63+
color: 'white',
64+
}}
65+
/>
66+
67+
<Text style={text}>Thank you for supporting Immich and open-source software</Text>
68+
69+
<Text style={text}>
70+
Your <strong>Immich</strong> license key is
71+
</Text>
72+
73+
<Section
74+
style={{
75+
textAlign: 'center',
76+
background: 'rgb(225, 225, 225)',
77+
borderRadius: '16px',
78+
marginBottom: '25px',
79+
}}
80+
>
81+
<Text style={{ fontFamily: 'monospace', fontWeight: 600, color: 'rgb(66, 80, 175)' }}>
82+
{'{{LICENSEKEY}}'}
83+
</Text>
84+
</Section>
85+
86+
{/* <Text style={text}>
87+
To activate your instance, you can click the following button or copy and paste the link below to your
88+
browser
89+
</Text>
90+
91+
<Row>
92+
<Column align="center">
93+
<Button
94+
style={button}
95+
href={`https://my.immich.app/link?target=activate_license&licenseKey={{LICENSEKEY}}&activationKey={{ACTIVATIONKEY}}`}
96+
>
97+
Activate
98+
</Button>
99+
</Column>
100+
</Row>
101+
102+
<Row>
103+
<Column align="center">
104+
<a
105+
style={{ marginTop: '50px', color: 'rgb(66, 80, 175)', fontSize: '0.9rem' }}
106+
href={`https://my.immich.app/link?target=activate_license&licenseKey={{LICENSEKEY}}&activationKey={{ACTIVATIONKEY}}`}
107+
>
108+
https://my.immich.app/link?target=activate_license&licenseKey={'{{LICENSEKEY}}'}&activationKey=
109+
{'{{ACTIVATIONKEY}}'}
110+
</a>
111+
</Column>
112+
</Row> */}
113+
</Section>
114+
115+
<Section style={{ textAlign: 'center' }}>
116+
<Row>
117+
<Column align="center">
118+
<Link href="https://futo.org">
119+
<Img
120+
src="https://futo.org/images/FutoMainLogo.svg"
121+
alt="FUTO"
122+
style={{
123+
height: '24px',
124+
marginTop: '25px',
125+
marginBottom: '25px',
126+
}}
127+
/>
128+
</Link>
129+
</Column>
130+
</Row>
131+
</Section>
132+
133+
<Hr style={{ color: 'rgb(66, 80, 175)', marginTop: '0' }} />
134+
135+
<Section style={{ textAlign: 'center' }}>
136+
<Column align="center">
137+
<Link href="https://apps.apple.com/sg/app/immich/id1613945652">
138+
<Img
139+
src={`https://immich.app/img/ios-app-store-badge.png`}
140+
alt="Immich"
141+
style={{ height: '72px', padding: '14px' }}
142+
/>
143+
</Link>
144+
<Link href="https://play.google.com/store/apps/details?id=app.alextran.immich">
145+
<Img src={`https://immich.app/img/google-play-badge.png`} height="96px" alt="Immich" />
146+
</Link>
147+
</Column>
148+
</Section>
149+
150+
<Text
151+
style={{
152+
color: '#6a737d',
153+
fontSize: '0.8rem',
154+
textAlign: 'center' as const,
155+
marginTop: '14px',
156+
}}
157+
>
158+
<Link href="https://immich.app">Immich</Link> project is available under GNU AGPL v3 license.
159+
</Text>
160+
</Container>
161+
</Body>
162+
</Html>
163+
);
164+
165+
LicenseEmail.PreviewProps = {};
166+
167+
export default LicenseEmail;
168+
169+
const text = {
170+
margin: '0 0 24px 0',
171+
textAlign: 'left' as const,
172+
fontSize: '16px',
173+
lineHeight: '24px',
174+
};
175+
176+
const button: CSS.Properties = {
177+
backgroundColor: 'rgb(66, 80, 175)',
178+
margin: '1em 0',
179+
padding: '0.75em 3em',
180+
color: '#fff',
181+
fontSize: '1em',
182+
fontWeight: 600,
183+
lineHeight: 1.5,
184+
textTransform: 'uppercase',
185+
borderRadius: '9999px',
186+
};

server/src/services/server.service.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ export class ServerService implements OnEvents {
164164
await this.systemMetadataRepository.delete(SystemMetadataKey.LICENSE);
165165
}
166166

167-
async getLicense(): Promise<LicenseKeyDto | null> {
167+
async getLicense(): Promise<LicenseResponseDto | null> {
168168
return this.systemMetadataRepository.get(SystemMetadataKey.LICENSE);
169169
}
170170

web/package-lock.json

+13
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

web/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"@typescript-eslint/parser": "^7.1.0",
4141
"@vitest/coverage-v8": "^1.3.1",
4242
"autoprefixer": "^10.4.17",
43+
"dotenv": "^16.4.5",
4344
"eslint": "^8.57.0",
4445
"eslint-config-prettier": "^9.1.0",
4546
"eslint-plugin-svelte": "^2.35.1",

web/src/app.d.ts

+5
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,8 @@ declare namespace svelteHTML {
2727
'on:zoomImage'?: () => void;
2828
}
2929
}
30+
31+
declare module '$env/static/public' {
32+
export const PUBLIC_IMMICH_PAY_HOST: string;
33+
export const PUBLIC_IMMICH_BUY_HOST: string;
34+
}

web/src/lib/components/shared-components/full-screen-modal.svelte

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
} else if (width === 'narrow') {
4040
modalWidth = 'w-[28rem]';
4141
} else {
42-
modalWidth = 'sm:max-w-lg';
42+
modalWidth = 'sm:max-w-4xl';
4343
}
4444
}
4545
</script>

0 commit comments

Comments
 (0)