neoagent 2.4.1-beta.23 → 2.4.1-beta.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/extensions/chrome-browser/icons/icon128.png +0 -0
- package/extensions/chrome-browser/icons/icon16.png +0 -0
- package/extensions/chrome-browser/icons/icon48.png +0 -0
- package/extensions/chrome-browser/icons/logo.svg +39 -18
- package/flutter_app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/flutter_app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/flutter_app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/flutter_app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/flutter_app/assets/branding/app_icon_1024.png +0 -0
- package/flutter_app/assets/branding/app_icon_128.png +0 -0
- package/flutter_app/assets/branding/app_icon_192.png +0 -0
- package/flutter_app/assets/branding/app_icon_256.png +0 -0
- package/flutter_app/assets/branding/app_icon_32.png +0 -0
- package/flutter_app/assets/branding/app_icon_512.png +0 -0
- package/flutter_app/assets/branding/app_icon_64.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_1024.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_128.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_192.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_256.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_32.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_512.png +0 -0
- package/flutter_app/assets/branding/app_icon_light_64.png +0 -0
- package/flutter_app/assets/branding/tray_icon_light_template.png +0 -0
- package/flutter_app/assets/branding/tray_icon_template.png +0 -0
- package/flutter_app/lib/features/onboarding/onboarding_chrome.dart +1 -1
- package/flutter_app/lib/features/onboarding/onboarding_companion_step.dart +1 -1
- package/flutter_app/lib/features/onboarding/onboarding_model_step.dart +1 -1
- package/flutter_app/lib/features/onboarding/onboarding_welcome_step.dart +2 -2
- package/flutter_app/lib/main_app_shell.dart +7 -7
- package/flutter_app/lib/main_shared.dart +1 -1
- package/flutter_app/linux/runner/resources/app_icon.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png +0 -0
- package/flutter_app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-1024.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-128.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-16.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-180.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-192.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-256.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-32.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-48.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-512.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon-64.png +0 -0
- package/flutter_app/tool/branding_source/neoagent-icon.svg +43 -0
- package/flutter_app/tool/generate_desktop_branding.py +137 -277
- package/flutter_app/web/favicon.png +0 -0
- package/flutter_app/web/favicon.svg +39 -18
- package/flutter_app/web/favicon_light.svg +39 -18
- package/flutter_app/web/icons/Icon-192-light.png +0 -0
- package/flutter_app/web/icons/Icon-192.png +0 -0
- package/flutter_app/web/icons/Icon-512-light.png +0 -0
- package/flutter_app/web/icons/Icon-512.png +0 -0
- package/flutter_app/web/icons/Icon-maskable-192-light.png +0 -0
- package/flutter_app/web/icons/Icon-maskable-192.png +0 -0
- package/flutter_app/web/icons/Icon-maskable-512-light.png +0 -0
- package/flutter_app/web/icons/Icon-maskable-512.png +0 -0
- package/flutter_app/windows/runner/resources/app_icon.ico +0 -0
- package/package.json +1 -1
- package/server/public/.last_build_id +1 -1
- package/server/public/assets/assets/branding/app_icon_256.png +0 -0
- package/server/public/assets/assets/branding/app_icon_512.png +0 -0
- package/server/public/assets/assets/branding/app_icon_light_256.png +0 -0
- package/server/public/assets/assets/branding/app_icon_light_512.png +0 -0
- package/server/public/assets/assets/branding/tray_icon_light_template.png +0 -0
- package/server/public/assets/assets/branding/tray_icon_template.png +0 -0
- package/server/public/assets/web/icons/Icon-192.png +0 -0
- package/server/public/favicon.png +0 -0
- package/server/public/favicon.svg +39 -18
- package/server/public/favicon_light.svg +39 -18
- package/server/public/flutter_bootstrap.js +2 -2
- package/server/public/icons/Icon-192-light.png +0 -0
- package/server/public/icons/Icon-192.png +0 -0
- package/server/public/icons/Icon-512-light.png +0 -0
- package/server/public/icons/Icon-512.png +0 -0
- package/server/public/icons/Icon-maskable-192-light.png +0 -0
- package/server/public/icons/Icon-maskable-192.png +0 -0
- package/server/public/icons/Icon-maskable-512-light.png +0 -0
- package/server/public/icons/Icon-maskable-512.png +0 -0
- package/server/public/main.dart.js +111 -111
|
@@ -4,10 +4,11 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
|
|
7
|
-
from PIL import Image, ImageDraw
|
|
7
|
+
from PIL import Image, ImageDraw
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
ROOT = Path(__file__).resolve().parents[1]
|
|
11
|
+
SOURCE_DIR = ROOT / "tool" / "branding_source"
|
|
11
12
|
BRANDING_DIR = ROOT / "assets" / "branding"
|
|
12
13
|
WEB_DIR = ROOT / "web"
|
|
13
14
|
WEB_ICONS_DIR = WEB_DIR / "icons"
|
|
@@ -19,294 +20,146 @@ SERVER_PUBLIC_DIR = ROOT.parent / "server" / "public"
|
|
|
19
20
|
SERVER_PUBLIC_ICONS_DIR = SERVER_PUBLIC_DIR / "icons"
|
|
20
21
|
STATIC_IMG_DIR = ROOT.parent / "static" / "img"
|
|
21
22
|
LANDING_LOGO_PATH = ROOT.parent / "landing" / "assets" / "logo.svg"
|
|
22
|
-
|
|
23
|
+
EXTENSION_ICON_DIR = ROOT.parent / "extensions" / "chrome-browser" / "icons"
|
|
24
|
+
EXTENSION_LOGO_PATH = EXTENSION_ICON_DIR / "logo.svg"
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
ACCENT_DARK = (158, 128, 82)
|
|
27
|
-
ACCENT_ALT_DARK = (67, 144, 129)
|
|
28
|
-
SYMBOL_LIGHT = (255, 247, 232, 255)
|
|
29
|
-
WHITE = (255, 255, 255, 255)
|
|
26
|
+
SOURCE_SVG = SOURCE_DIR / "neoagent-icon.svg"
|
|
27
|
+
SOURCE_PNG_SIZES = (16, 32, 48, 64, 128, 180, 192, 256, 512, 1024)
|
|
30
28
|
TRANSPARENT = (0, 0, 0, 0)
|
|
29
|
+
WHITE = (255, 255, 255, 255)
|
|
30
|
+
BLACK = (0, 0, 0, 255)
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
def
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return (
|
|
43
|
-
mix_channel(color[0], target, amount),
|
|
44
|
-
mix_channel(color[1], target, amount),
|
|
45
|
-
mix_channel(color[2], target, amount),
|
|
46
|
-
)
|
|
33
|
+
def ensure_dirs() -> None:
|
|
34
|
+
BRANDING_DIR.mkdir(parents=True, exist_ok=True)
|
|
35
|
+
WEB_ICONS_DIR.mkdir(parents=True, exist_ok=True)
|
|
36
|
+
MAC_ICON_DIR.mkdir(parents=True, exist_ok=True)
|
|
37
|
+
LINUX_ICON_DIR.mkdir(parents=True, exist_ok=True)
|
|
38
|
+
SERVER_PUBLIC_ICONS_DIR.mkdir(parents=True, exist_ok=True)
|
|
39
|
+
STATIC_IMG_DIR.mkdir(parents=True, exist_ok=True)
|
|
40
|
+
LANDING_LOGO_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
41
|
+
EXTENSION_ICON_DIR.mkdir(parents=True, exist_ok=True)
|
|
47
42
|
|
|
48
43
|
|
|
49
|
-
def
|
|
50
|
-
size
|
|
51
|
-
start: tuple[int, int, int],
|
|
52
|
-
end: tuple[int, int, int],
|
|
53
|
-
) -> Image.Image:
|
|
54
|
-
img = Image.new("RGBA", (size, size), TRANSPARENT)
|
|
55
|
-
px = img.load()
|
|
56
|
-
for y in range(size):
|
|
57
|
-
for x in range(size):
|
|
58
|
-
tx = x / max(size - 1, 1)
|
|
59
|
-
ty = y / max(size - 1, 1)
|
|
60
|
-
diagonal = (tx * 0.58) + (ty * 0.42)
|
|
61
|
-
glow = max(0.0, 1.0 - (((tx - 0.25) ** 2 + (ty - 0.18) ** 2) ** 0.5) / 0.58)
|
|
62
|
-
shade = max(0.0, 1.0 - (((tx - 0.86) ** 2 + (ty - 0.94) ** 2) ** 0.5) / 0.72)
|
|
63
|
-
t = min(1.0, max(0.0, diagonal + glow * 0.12 - shade * 0.08))
|
|
64
|
-
base = (
|
|
65
|
-
int(lerp(start[0], end[0], t)),
|
|
66
|
-
int(lerp(start[1], end[1], t)),
|
|
67
|
-
int(lerp(start[2], end[2], t)),
|
|
68
|
-
)
|
|
69
|
-
lit = mix_color(base, 255, glow * 0.14)
|
|
70
|
-
final = mix_color(lit, 0, shade * 0.16)
|
|
71
|
-
px[x, y] = (
|
|
72
|
-
final[0],
|
|
73
|
-
final[1],
|
|
74
|
-
final[2],
|
|
75
|
-
255,
|
|
76
|
-
)
|
|
77
|
-
return img
|
|
44
|
+
def source_png_path(size: int) -> Path:
|
|
45
|
+
return SOURCE_DIR / f"neoagent-icon-{size}.png"
|
|
78
46
|
|
|
79
47
|
|
|
80
|
-
def
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
48
|
+
def load_source_icon(size: int) -> Image.Image:
|
|
49
|
+
if size in SOURCE_PNG_SIZES and source_png_path(size).exists():
|
|
50
|
+
return Image.open(source_png_path(size)).convert("RGBA")
|
|
51
|
+
source = Image.open(source_png_path(1024)).convert("RGBA")
|
|
52
|
+
return source.resize((size, size), Image.Resampling.LANCZOS)
|
|
85
53
|
|
|
86
|
-
top = [point(0.5, 0.08), point(0.92, 0.35), point(0.5, 0.53), point(0.08, 0.35)]
|
|
87
|
-
middle = [point(0.5, 0.43), point(0.9, 0.64), point(0.5, 0.76), point(0.1, 0.64)]
|
|
88
|
-
bottom = [point(0.5, 0.67), point(0.86, 0.86), point(0.5, 0.96), point(0.14, 0.86)]
|
|
89
|
-
return top, middle, bottom
|
|
90
54
|
|
|
55
|
+
def save_icon(path: Path, size: int) -> None:
|
|
56
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
57
|
+
image = load_source_icon(size)
|
|
58
|
+
if image.size != (size, size):
|
|
59
|
+
image = image.resize((size, size), Image.Resampling.LANCZOS)
|
|
60
|
+
image.save(path, format="PNG")
|
|
91
61
|
|
|
92
|
-
def draw_logo(draw: ImageDraw.ImageDraw, size: int, color: tuple[int, int, int, int]) -> None:
|
|
93
|
-
top, middle, bottom = logo_paths(size)
|
|
94
|
-
draw.polygon(top, fill=color)
|
|
95
|
-
draw.polygon(middle, fill=color)
|
|
96
|
-
draw.polygon(bottom, fill=color)
|
|
97
62
|
|
|
63
|
+
def write_source_svg(path: Path) -> None:
|
|
64
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
65
|
+
svg = SOURCE_SVG.read_text(encoding="utf-8")
|
|
66
|
+
svg = svg.replace(
|
|
67
|
+
'stroke="rgba(255,255,255,0.16)"',
|
|
68
|
+
'stroke="#ffffff" stroke-opacity="0.16"',
|
|
69
|
+
)
|
|
70
|
+
path.write_text(svg, encoding="utf-8")
|
|
98
71
|
|
|
99
|
-
def make_app_icon(size: int, *, light: bool = False) -> Image.Image:
|
|
100
|
-
canvas = Image.new("RGBA", (size, size), TRANSPARENT)
|
|
101
|
-
start = ACCENT if light else ACCENT_DARK
|
|
102
|
-
end = ACCENT_ALT if light else ACCENT_ALT_DARK
|
|
103
|
-
symbol = SYMBOL_LIGHT if light else WHITE
|
|
104
72
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
base_mask = Image.new("L", (size, size), 0)
|
|
117
|
-
mask_draw = ImageDraw.Draw(base_mask)
|
|
118
|
-
base_rect = (size * 0.08, size * 0.08, size * 0.92, size * 0.92)
|
|
119
|
-
mask_draw.rounded_rectangle(base_rect, radius=corner, fill=255)
|
|
120
|
-
|
|
121
|
-
base = gradient_background(size, start, end)
|
|
122
|
-
clipped = Image.new("RGBA", (size, size), TRANSPARENT)
|
|
123
|
-
clipped.paste(base, mask=base_mask)
|
|
124
|
-
canvas.alpha_composite(clipped)
|
|
125
|
-
|
|
126
|
-
shine = Image.new("RGBA", (size, size), TRANSPARENT)
|
|
127
|
-
shine_draw = ImageDraw.Draw(shine)
|
|
128
|
-
shine_draw.ellipse(
|
|
129
|
-
(size * -0.12, size * -0.18, size * 0.78, size * 0.58),
|
|
130
|
-
fill=(255, 255, 255, 30 if light else 42),
|
|
131
|
-
)
|
|
132
|
-
shine.putalpha(Image.composite(shine.getchannel("A"), Image.new("L", (size, size), 0), base_mask))
|
|
133
|
-
canvas.alpha_composite(shine)
|
|
134
|
-
|
|
135
|
-
lower_glaze = Image.new("RGBA", (size, size), TRANSPARENT)
|
|
136
|
-
lower_draw = ImageDraw.Draw(lower_glaze)
|
|
137
|
-
lower_draw.rounded_rectangle(
|
|
138
|
-
base_rect,
|
|
139
|
-
radius=corner,
|
|
140
|
-
fill=(0, 0, 0, 18 if light else 12),
|
|
141
|
-
)
|
|
142
|
-
lower_mask = Image.new("L", (size, size), 0)
|
|
143
|
-
lower_mask_draw = ImageDraw.Draw(lower_mask)
|
|
144
|
-
lower_mask_draw.rectangle((0, size * 0.55, size, size), fill=255)
|
|
145
|
-
lower_glaze.putalpha(Image.composite(lower_glaze.getchannel("A"), Image.new("L", (size, size), 0), lower_mask))
|
|
146
|
-
canvas.alpha_composite(lower_glaze)
|
|
147
|
-
|
|
148
|
-
ring = Image.new("RGBA", (size, size), TRANSPARENT)
|
|
149
|
-
ring_draw = ImageDraw.Draw(ring)
|
|
150
|
-
ring_draw.rounded_rectangle(
|
|
151
|
-
base_rect,
|
|
152
|
-
radius=corner,
|
|
153
|
-
outline=(255, 255, 255, 58 if light else 48),
|
|
154
|
-
width=max(1, round(size * 0.012)),
|
|
155
|
-
)
|
|
156
|
-
inset = size * 0.018
|
|
157
|
-
ring_draw.rounded_rectangle(
|
|
73
|
+
def draw_scaled_circle(
|
|
74
|
+
draw: ImageDraw.ImageDraw,
|
|
75
|
+
size: int,
|
|
76
|
+
center_x: float,
|
|
77
|
+
center_y: float,
|
|
78
|
+
radius: float,
|
|
79
|
+
color: tuple[int, int, int, int],
|
|
80
|
+
) -> None:
|
|
81
|
+
scale = size / 100
|
|
82
|
+
draw.ellipse(
|
|
158
83
|
(
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
84
|
+
(center_x - radius) * scale,
|
|
85
|
+
(center_y - radius) * scale,
|
|
86
|
+
(center_x + radius) * scale,
|
|
87
|
+
(center_y + radius) * scale,
|
|
163
88
|
),
|
|
164
|
-
|
|
165
|
-
outline=(0, 0, 0, 26 if light else 20),
|
|
166
|
-
width=max(1, round(size * 0.006)),
|
|
167
|
-
)
|
|
168
|
-
canvas.alpha_composite(ring)
|
|
169
|
-
|
|
170
|
-
glyph_shadow = Image.new("RGBA", (size, size), TRANSPARENT)
|
|
171
|
-
shadow_draw = ImageDraw.Draw(glyph_shadow)
|
|
172
|
-
draw_logo(shadow_draw, size, (0, 0, 0, 76 if light else 58))
|
|
173
|
-
glyph_shadow = glyph_shadow.transform(
|
|
174
|
-
glyph_shadow.size,
|
|
175
|
-
Image.Transform.AFFINE,
|
|
176
|
-
(1, 0, 0, 0, 1, size * 0.018),
|
|
177
|
-
resample=Image.Resampling.BICUBIC,
|
|
89
|
+
fill=color,
|
|
178
90
|
)
|
|
179
|
-
glyph_shadow = glyph_shadow.filter(ImageFilter.GaussianBlur(radius=max(1, size * 0.006)))
|
|
180
|
-
canvas.alpha_composite(glyph_shadow)
|
|
181
|
-
|
|
182
|
-
glyph = Image.new("RGBA", (size, size), TRANSPARENT)
|
|
183
|
-
draw = ImageDraw.Draw(glyph)
|
|
184
|
-
draw_logo(draw, size, symbol)
|
|
185
|
-
canvas.alpha_composite(glyph)
|
|
186
|
-
|
|
187
|
-
glyph_highlight = Image.new("RGBA", (size, size), TRANSPARENT)
|
|
188
|
-
highlight_draw = ImageDraw.Draw(glyph_highlight)
|
|
189
|
-
draw_logo(highlight_draw, size, (255, 255, 255, 26 if light else 34))
|
|
190
|
-
glyph_highlight = glyph_highlight.transform(
|
|
191
|
-
glyph_highlight.size,
|
|
192
|
-
Image.Transform.AFFINE,
|
|
193
|
-
(1, 0, 0, 0, 1, -size * 0.012),
|
|
194
|
-
resample=Image.Resampling.BICUBIC,
|
|
195
|
-
)
|
|
196
|
-
canvas.alpha_composite(glyph_highlight)
|
|
197
|
-
return canvas
|
|
198
91
|
|
|
199
92
|
|
|
200
93
|
def make_tray_template(
|
|
201
94
|
size: int = 64,
|
|
202
|
-
color: tuple[int, int, int, int] =
|
|
95
|
+
color: tuple[int, int, int, int] = BLACK,
|
|
203
96
|
) -> Image.Image:
|
|
204
97
|
img = Image.new("RGBA", (size, size), TRANSPARENT)
|
|
205
98
|
draw = ImageDraw.Draw(img)
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
99
|
+
scale = size / 100
|
|
100
|
+
width = max(2, round(size * 0.078))
|
|
101
|
+
center = 50 * scale
|
|
209
102
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
103
|
+
draw.arc(
|
|
104
|
+
(
|
|
105
|
+
(50 - 30) * scale,
|
|
106
|
+
(50 - 30) * scale,
|
|
107
|
+
(50 + 30) * scale,
|
|
108
|
+
(50 + 30) * scale,
|
|
109
|
+
),
|
|
110
|
+
start=158,
|
|
111
|
+
end=444,
|
|
112
|
+
fill=color,
|
|
113
|
+
width=width,
|
|
114
|
+
)
|
|
115
|
+
draw.arc(
|
|
116
|
+
(
|
|
117
|
+
(50 - 17) * scale,
|
|
118
|
+
(50 - 17) * scale,
|
|
119
|
+
(50 + 17) * scale,
|
|
120
|
+
(50 + 17) * scale,
|
|
121
|
+
),
|
|
122
|
+
start=68,
|
|
123
|
+
end=330,
|
|
124
|
+
fill=color,
|
|
125
|
+
width=width,
|
|
126
|
+
)
|
|
127
|
+
draw_scaled_circle(draw, size, 50, 50, 7, color)
|
|
128
|
+
draw_scaled_circle(draw, size, 50, 20, 5.6, color)
|
|
129
|
+
|
|
130
|
+
# Slightly round arc ends so the template keeps the supplied logo's soft tube feel.
|
|
131
|
+
end_radius = width / 2
|
|
132
|
+
for x, y in ((77.2, 74.8), (80.0, 41.2), (32.0, 29.7), (68.8, 39.2)):
|
|
133
|
+
draw.ellipse(
|
|
134
|
+
(
|
|
135
|
+
x * scale - end_radius,
|
|
136
|
+
y * scale - end_radius,
|
|
137
|
+
x * scale + end_radius,
|
|
138
|
+
y * scale + end_radius,
|
|
139
|
+
),
|
|
140
|
+
fill=color,
|
|
141
|
+
)
|
|
219
142
|
|
|
143
|
+
# Keep the symbol optically centered inside the menu-bar bounds.
|
|
144
|
+
return img.crop((0, 2, size, size + 2))
|
|
220
145
|
|
|
221
|
-
def write_text(path: Path, content: str) -> None:
|
|
222
|
-
path.write_text(content, encoding="utf-8")
|
|
223
146
|
|
|
147
|
+
def main() -> None:
|
|
148
|
+
ensure_dirs()
|
|
224
149
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
def write_favicon_svg(path: Path, *, light: bool = False) -> None:
|
|
231
|
-
start = ACCENT if light else ACCENT_DARK
|
|
232
|
-
end = ACCENT_ALT if light else ACCENT_ALT_DARK
|
|
233
|
-
symbol = "#fff9ed" if light else "#ffffff"
|
|
234
|
-
stroke = "#000000" if light else "#ffffff"
|
|
235
|
-
stroke_opacity = "0.24" if light else "0.16"
|
|
236
|
-
glow = "#ffffff" if light else "#fff4d8"
|
|
237
|
-
top_opacity = "0.20" if light else "0.24"
|
|
238
|
-
shade_opacity = "0.12" if light else "0.08"
|
|
239
|
-
svg = f"""<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
|
240
|
-
<defs>
|
|
241
|
-
<linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
242
|
-
<stop offset="0%" stop-color="#{start[0]:02x}{start[1]:02x}{start[2]:02x}"/>
|
|
243
|
-
<stop offset="100%" stop-color="#{end[0]:02x}{end[1]:02x}{end[2]:02x}"/>
|
|
244
|
-
</linearGradient>
|
|
245
|
-
<radialGradient id="shine" cx="24%" cy="15%" r="70%">
|
|
246
|
-
<stop offset="0%" stop-color="{glow}" stop-opacity="{top_opacity}"/>
|
|
247
|
-
<stop offset="100%" stop-color="{glow}" stop-opacity="0"/>
|
|
248
|
-
</radialGradient>
|
|
249
|
-
</defs>
|
|
250
|
-
<rect x="2.5" y="2.5" width="27" height="27" rx="9" ry="9" fill="url(#bg)" stroke="{stroke}" stroke-opacity="{stroke_opacity}" stroke-width="1"/>
|
|
251
|
-
<rect x="2.5" y="2.5" width="27" height="27" rx="9" ry="9" fill="url(#shine)"/>
|
|
252
|
-
<path d="M2.5 17h27v3.5c0 5-4 9-9 9h-9c-5 0-9-4-9-9Z" fill="#000000" opacity="{shade_opacity}"/>
|
|
253
|
-
<rect x="3" y="3" width="26" height="26" rx="8.5" ry="8.5" fill="none" stroke="#ffffff" stroke-opacity="0.18" stroke-width="1"/>
|
|
254
|
-
<path d="M16 6.25 26.15 12.3 16 16.3 5.85 12.3Z" fill="#000000" opacity="0.20" transform="translate(0 0.65)"/>
|
|
255
|
-
<path d="M16 14.75 25.85 19.45 16 22.25 6.15 19.45Z" fill="#000000" opacity="0.20" transform="translate(0 0.65)"/>
|
|
256
|
-
<path d="M16 20.45 24.85 24.75 16 26.85 7.15 24.75Z" fill="#000000" opacity="0.20" transform="translate(0 0.65)"/>
|
|
257
|
-
<path d="M16 5.7 26.8 12.1 16 16.5 5.2 12.1Z" fill="{symbol}"/>
|
|
258
|
-
<path d="M16 14.2 26.5 19.3 16 22.4 5.5 19.3Z" fill="{symbol}"/>
|
|
259
|
-
<path d="M16 20 25.4 24.6 16 27 6.6 24.6Z" fill="{symbol}"/>
|
|
260
|
-
</svg>
|
|
261
|
-
"""
|
|
262
|
-
write_text(path, svg)
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
def save_png(image: Image.Image, path: Path, size: int) -> None:
|
|
266
|
-
image.resize((size, size), Image.Resampling.LANCZOS).save(path, format="PNG")
|
|
150
|
+
for size in (1024, 512, 256, 192, 128, 64, 32):
|
|
151
|
+
save_icon(BRANDING_DIR / f"app_icon_{size}.png", size)
|
|
152
|
+
save_icon(BRANDING_DIR / f"app_icon_light_{size}.png", size)
|
|
267
153
|
|
|
154
|
+
make_tray_template(64).save(BRANDING_DIR / "tray_icon_template.png", format="PNG")
|
|
155
|
+
make_tray_template(64, WHITE).save(BRANDING_DIR / "tray_icon_light_template.png", format="PNG")
|
|
268
156
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
master = make_app_icon(1024)
|
|
272
|
-
light_master = make_app_icon(1024, light=True)
|
|
273
|
-
|
|
274
|
-
save_png(master, BRANDING_DIR / "app_icon_1024.png", 1024)
|
|
275
|
-
save_png(master, BRANDING_DIR / "app_icon_512.png", 512)
|
|
276
|
-
save_png(master, BRANDING_DIR / "app_icon_256.png", 256)
|
|
277
|
-
save_png(master, BRANDING_DIR / "app_icon_192.png", 192)
|
|
278
|
-
save_png(master, BRANDING_DIR / "app_icon_128.png", 128)
|
|
279
|
-
save_png(master, BRANDING_DIR / "app_icon_64.png", 64)
|
|
280
|
-
save_png(master, BRANDING_DIR / "app_icon_32.png", 32)
|
|
281
|
-
save_png(light_master, BRANDING_DIR / "app_icon_light_1024.png", 1024)
|
|
282
|
-
save_png(light_master, BRANDING_DIR / "app_icon_light_512.png", 512)
|
|
283
|
-
save_png(light_master, BRANDING_DIR / "app_icon_light_256.png", 256)
|
|
284
|
-
save_png(light_master, BRANDING_DIR / "app_icon_light_192.png", 192)
|
|
285
|
-
save_png(light_master, BRANDING_DIR / "app_icon_light_128.png", 128)
|
|
286
|
-
save_png(light_master, BRANDING_DIR / "app_icon_light_64.png", 64)
|
|
287
|
-
save_png(light_master, BRANDING_DIR / "app_icon_light_32.png", 32)
|
|
288
|
-
|
|
289
|
-
tray = make_tray_template(64)
|
|
290
|
-
save_png(tray, BRANDING_DIR / "tray_icon_template.png", 64)
|
|
291
|
-
light_tray = make_tray_template(64, WHITE)
|
|
292
|
-
save_png(light_tray, BRANDING_DIR / "tray_icon_light_template.png", 64)
|
|
293
|
-
|
|
294
|
-
icon_sizes = {
|
|
295
|
-
16: "app_icon_16.png",
|
|
296
|
-
32: "app_icon_32.png",
|
|
297
|
-
64: "app_icon_64.png",
|
|
298
|
-
128: "app_icon_128.png",
|
|
299
|
-
256: "app_icon_256.png",
|
|
300
|
-
512: "app_icon_512.png",
|
|
301
|
-
1024: "app_icon_1024.png",
|
|
302
|
-
}
|
|
303
|
-
for size, filename in icon_sizes.items():
|
|
304
|
-
save_png(master, MAC_ICON_DIR / filename, size)
|
|
157
|
+
for size in (16, 32, 64, 128, 256, 512, 1024):
|
|
158
|
+
save_icon(MAC_ICON_DIR / f"app_icon_{size}.png", size)
|
|
305
159
|
|
|
306
|
-
|
|
160
|
+
save_icon(LINUX_ICON_DIR / "app_icon.png", 256)
|
|
307
161
|
|
|
308
|
-
|
|
309
|
-
master_for_ico.save(
|
|
162
|
+
load_source_icon(256).save(
|
|
310
163
|
WINDOWS_ICON_PATH,
|
|
311
164
|
format="ICO",
|
|
312
165
|
sizes=[(16, 16), (24, 24), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)],
|
|
@@ -317,26 +170,33 @@ def main() -> None:
|
|
|
317
170
|
512: "Icon-512.png",
|
|
318
171
|
}
|
|
319
172
|
for size, filename in web_icon_sizes.items():
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
173
|
+
save_icon(WEB_ICONS_DIR / filename, size)
|
|
174
|
+
save_icon(WEB_ICONS_DIR / filename.replace("Icon-", "Icon-maskable-"), size)
|
|
175
|
+
save_icon(WEB_ICONS_DIR / filename.replace(".png", "-light.png"), size)
|
|
176
|
+
save_icon(WEB_ICONS_DIR / filename.replace("Icon-", "Icon-maskable-").replace(".png", "-light.png"), size)
|
|
177
|
+
save_icon(SERVER_PUBLIC_ICONS_DIR / filename, size)
|
|
178
|
+
save_icon(SERVER_PUBLIC_ICONS_DIR / filename.replace("Icon-", "Icon-maskable-"), size)
|
|
179
|
+
|
|
180
|
+
save_icon(WEB_DIR / "favicon.png", 32)
|
|
181
|
+
save_icon(SERVER_PUBLIC_DIR / "favicon.png", 32)
|
|
182
|
+
write_source_svg(WEB_DIR / "favicon.svg")
|
|
183
|
+
write_source_svg(WEB_DIR / "favicon_light.svg")
|
|
184
|
+
write_source_svg(SERVER_PUBLIC_DIR / "favicon.svg")
|
|
185
|
+
write_source_svg(SERVER_PUBLIC_DIR / "favicon_light.svg")
|
|
186
|
+
write_source_svg(LANDING_LOGO_PATH)
|
|
187
|
+
write_source_svg(EXTENSION_LOGO_PATH)
|
|
188
|
+
|
|
189
|
+
for size in (16, 48, 128):
|
|
190
|
+
save_icon(EXTENSION_ICON_DIR / f"icon{size}.png", size)
|
|
191
|
+
|
|
192
|
+
save_icon(STATIC_IMG_DIR / "app_icon.png", 512)
|
|
193
|
+
save_icon(STATIC_IMG_DIR / "app_icon_light.png", 512)
|
|
194
|
+
save_icon(SERVER_PUBLIC_DIR / "assets" / "assets" / "branding" / "app_icon_256.png", 256)
|
|
195
|
+
make_tray_template(64).save(
|
|
196
|
+
SERVER_PUBLIC_DIR / "assets" / "assets" / "branding" / "tray_icon_template.png",
|
|
197
|
+
format="PNG",
|
|
198
|
+
)
|
|
199
|
+
save_icon(SERVER_PUBLIC_DIR / "assets" / "web" / "icons" / "Icon-192.png", 192)
|
|
340
200
|
|
|
341
201
|
android_icon_sizes = {
|
|
342
202
|
"mipmap-mdpi": 48,
|
|
@@ -346,7 +206,7 @@ def main() -> None:
|
|
|
346
206
|
"mipmap-xxxhdpi": 192,
|
|
347
207
|
}
|
|
348
208
|
for folder, size in android_icon_sizes.items():
|
|
349
|
-
|
|
209
|
+
save_icon(ANDROID_RES_DIR / folder / "ic_launcher.png", size)
|
|
350
210
|
|
|
351
211
|
|
|
352
212
|
if __name__ == "__main__":
|
|
Binary file
|
|
@@ -1,22 +1,43 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 100 100">
|
|
2
2
|
<defs>
|
|
3
|
-
<linearGradient id="
|
|
4
|
-
<stop offset="0%" stop-color="#
|
|
5
|
-
<stop offset="100%" stop-color="#
|
|
3
|
+
<linearGradient id="tile" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
+
<stop offset="0%" stop-color="#705331"></stop>
|
|
5
|
+
<stop offset="100%" stop-color="#22564c"></stop>
|
|
6
6
|
</linearGradient>
|
|
7
|
-
<radialGradient id="shine" cx="
|
|
8
|
-
<stop offset="0%" stop-color="#
|
|
9
|
-
<stop offset="100%" stop-color="#
|
|
7
|
+
<radialGradient id="shine" cx="26%" cy="14%" r="72%">
|
|
8
|
+
<stop offset="0%" stop-color="#ffffff" stop-opacity="0.22"></stop>
|
|
9
|
+
<stop offset="100%" stop-color="#ffffff" stop-opacity="0"></stop>
|
|
10
10
|
</radialGradient>
|
|
11
|
+
<radialGradient id="core" cx="38%" cy="32%" r="75%">
|
|
12
|
+
<stop offset="0%" stop-color="#fffdf6"></stop>
|
|
13
|
+
<stop offset="48%" stop-color="#eee3cc"></stop>
|
|
14
|
+
<stop offset="100%" stop-color="#b5a888"></stop>
|
|
15
|
+
</radialGradient>
|
|
16
|
+
<radialGradient id="node" cx="36%" cy="30%" r="80%">
|
|
17
|
+
<stop offset="0%" stop-color="#f8dca8"></stop>
|
|
18
|
+
<stop offset="52%" stop-color="#d3a85f"></stop>
|
|
19
|
+
<stop offset="100%" stop-color="#9b6f2f"></stop>
|
|
20
|
+
</radialGradient>
|
|
21
|
+
<linearGradient id="tube" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
22
|
+
<stop offset="0%" stop-color="#fffaf0"></stop>
|
|
23
|
+
<stop offset="52%" stop-color="#efe7d6"></stop>
|
|
24
|
+
<stop offset="100%" stop-color="#cabf9f"></stop>
|
|
25
|
+
</linearGradient>
|
|
26
|
+
<filter id="sh" x="-30%" y="-30%" width="160%" height="160%">
|
|
27
|
+
<feDropShadow dx="0" dy="1.1" stdDeviation="1.1" flood-color="#000000" flood-opacity="0.45"></feDropShadow>
|
|
28
|
+
</filter>
|
|
29
|
+
<clipPath id="tc"><rect x="0" y="0" width="100" height="100" rx="22.5"></rect></clipPath>
|
|
11
30
|
</defs>
|
|
12
|
-
<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
</
|
|
31
|
+
<g clip-path="url(#tc)">
|
|
32
|
+
<rect x="0" y="0" width="100" height="100" fill="url(#tile)"></rect>
|
|
33
|
+
<rect x="0" y="0" width="100" height="100" fill="url(#shine)"></rect>
|
|
34
|
+
<g fill="none" stroke="url(#tube)" stroke-linecap="round" filter="url(#sh)">
|
|
35
|
+
<circle cx="50" cy="50" r="17" stroke-width="5" stroke-dasharray="78 29" transform="rotate(-35 50 50)" stroke-opacity="0.92"></circle>
|
|
36
|
+
<circle cx="50" cy="50" r="30" stroke-width="5" stroke-dasharray="150 39" transform="rotate(70 50 50)" stroke-opacity="0.8"></circle>
|
|
37
|
+
</g>
|
|
38
|
+
<circle cx="50" cy="50" r="7" fill="url(#core)"></circle>
|
|
39
|
+
<circle cx="50" cy="20" r="5.6" fill="url(#node)"></circle>
|
|
40
|
+
<circle cx="48" cy="18.4" r="1.7" fill="#fff7e6" fill-opacity="0.8"></circle>
|
|
41
|
+
</g>
|
|
42
|
+
<rect x="0.6" y="0.6" width="98.8" height="98.8" rx="22" fill="none" stroke="#ffffff" stroke-opacity="0.16" stroke-width="1.2"></rect>
|
|
43
|
+
</svg>
|
|
@@ -1,22 +1,43 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 100 100">
|
|
2
2
|
<defs>
|
|
3
|
-
<linearGradient id="
|
|
4
|
-
<stop offset="0%" stop-color="#
|
|
5
|
-
<stop offset="100%" stop-color="#
|
|
3
|
+
<linearGradient id="tile" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
+
<stop offset="0%" stop-color="#705331"></stop>
|
|
5
|
+
<stop offset="100%" stop-color="#22564c"></stop>
|
|
6
6
|
</linearGradient>
|
|
7
|
-
<radialGradient id="shine" cx="
|
|
8
|
-
<stop offset="0%" stop-color="#ffffff" stop-opacity="0.
|
|
9
|
-
<stop offset="100%" stop-color="#ffffff" stop-opacity="0"
|
|
7
|
+
<radialGradient id="shine" cx="26%" cy="14%" r="72%">
|
|
8
|
+
<stop offset="0%" stop-color="#ffffff" stop-opacity="0.22"></stop>
|
|
9
|
+
<stop offset="100%" stop-color="#ffffff" stop-opacity="0"></stop>
|
|
10
10
|
</radialGradient>
|
|
11
|
+
<radialGradient id="core" cx="38%" cy="32%" r="75%">
|
|
12
|
+
<stop offset="0%" stop-color="#fffdf6"></stop>
|
|
13
|
+
<stop offset="48%" stop-color="#eee3cc"></stop>
|
|
14
|
+
<stop offset="100%" stop-color="#b5a888"></stop>
|
|
15
|
+
</radialGradient>
|
|
16
|
+
<radialGradient id="node" cx="36%" cy="30%" r="80%">
|
|
17
|
+
<stop offset="0%" stop-color="#f8dca8"></stop>
|
|
18
|
+
<stop offset="52%" stop-color="#d3a85f"></stop>
|
|
19
|
+
<stop offset="100%" stop-color="#9b6f2f"></stop>
|
|
20
|
+
</radialGradient>
|
|
21
|
+
<linearGradient id="tube" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
22
|
+
<stop offset="0%" stop-color="#fffaf0"></stop>
|
|
23
|
+
<stop offset="52%" stop-color="#efe7d6"></stop>
|
|
24
|
+
<stop offset="100%" stop-color="#cabf9f"></stop>
|
|
25
|
+
</linearGradient>
|
|
26
|
+
<filter id="sh" x="-30%" y="-30%" width="160%" height="160%">
|
|
27
|
+
<feDropShadow dx="0" dy="1.1" stdDeviation="1.1" flood-color="#000000" flood-opacity="0.45"></feDropShadow>
|
|
28
|
+
</filter>
|
|
29
|
+
<clipPath id="tc"><rect x="0" y="0" width="100" height="100" rx="22.5"></rect></clipPath>
|
|
11
30
|
</defs>
|
|
12
|
-
<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
</
|
|
31
|
+
<g clip-path="url(#tc)">
|
|
32
|
+
<rect x="0" y="0" width="100" height="100" fill="url(#tile)"></rect>
|
|
33
|
+
<rect x="0" y="0" width="100" height="100" fill="url(#shine)"></rect>
|
|
34
|
+
<g fill="none" stroke="url(#tube)" stroke-linecap="round" filter="url(#sh)">
|
|
35
|
+
<circle cx="50" cy="50" r="17" stroke-width="5" stroke-dasharray="78 29" transform="rotate(-35 50 50)" stroke-opacity="0.92"></circle>
|
|
36
|
+
<circle cx="50" cy="50" r="30" stroke-width="5" stroke-dasharray="150 39" transform="rotate(70 50 50)" stroke-opacity="0.8"></circle>
|
|
37
|
+
</g>
|
|
38
|
+
<circle cx="50" cy="50" r="7" fill="url(#core)"></circle>
|
|
39
|
+
<circle cx="50" cy="20" r="5.6" fill="url(#node)"></circle>
|
|
40
|
+
<circle cx="48" cy="18.4" r="1.7" fill="#fff7e6" fill-opacity="0.8"></circle>
|
|
41
|
+
</g>
|
|
42
|
+
<rect x="0.6" y="0.6" width="98.8" height="98.8" rx="22" fill="none" stroke="#ffffff" stroke-opacity="0.16" stroke-width="1.2"></rect>
|
|
43
|
+
</svg>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|