chore: apply mix format to codebase
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -31,7 +31,8 @@ defmodule SimpleshopTheme.Images.Optimizer do
|
||||
{width, _height, _} <- Image.shape(image),
|
||||
{:ok, resized} <- maybe_resize(image, width),
|
||||
{final_width, final_height, _} <- Image.shape(resized),
|
||||
{:ok, webp_data} <- Image.write(resized, :memory, suffix: ".webp", quality: @storage_quality) do
|
||||
{:ok, webp_data} <-
|
||||
Image.write(resized, :memory, suffix: ".webp", quality: @storage_quality) do
|
||||
{:ok, webp_data, final_width, final_height}
|
||||
end
|
||||
rescue
|
||||
@@ -191,9 +192,20 @@ defmodule SimpleshopTheme.Images.Optimizer do
|
||||
widths = applicable_widths(source_width)
|
||||
|
||||
tasks = [
|
||||
Task.async(fn -> generate_variant_to_dir(vips_image, output_basename, output_dir, "thumb", :jpg, @thumb_size) end)
|
||||
Task.async(fn ->
|
||||
generate_variant_to_dir(
|
||||
vips_image,
|
||||
output_basename,
|
||||
output_dir,
|
||||
"thumb",
|
||||
:jpg,
|
||||
@thumb_size
|
||||
)
|
||||
end)
|
||||
| for w <- widths, fmt <- @pregenerated_formats do
|
||||
Task.async(fn -> generate_variant_to_dir(vips_image, output_basename, output_dir, w, fmt, w) end)
|
||||
Task.async(fn ->
|
||||
generate_variant_to_dir(vips_image, output_basename, output_dir, w, fmt, w)
|
||||
end)
|
||||
end
|
||||
]
|
||||
|
||||
|
||||
@@ -59,7 +59,9 @@ defmodule SimpleshopTheme.Images.VariantCache do
|
||||
if to_process == [] do
|
||||
Logger.info("[VariantCache] All database image variants up to date")
|
||||
else
|
||||
Logger.info("[VariantCache] Enqueueing #{length(to_process)} database images for processing")
|
||||
Logger.info(
|
||||
"[VariantCache] Enqueueing #{length(to_process)} database images for processing"
|
||||
)
|
||||
|
||||
Enum.each(to_process, fn image ->
|
||||
image
|
||||
|
||||
@@ -119,7 +119,12 @@ defmodule SimpleshopTheme.Media do
|
||||
|
||||
"""
|
||||
def get_logo do
|
||||
Repo.one(from i in ImageSchema, where: i.image_type == "logo", order_by: [desc: i.inserted_at], limit: 1)
|
||||
Repo.one(
|
||||
from i in ImageSchema,
|
||||
where: i.image_type == "logo",
|
||||
order_by: [desc: i.inserted_at],
|
||||
limit: 1
|
||||
)
|
||||
end
|
||||
|
||||
@doc """
|
||||
@@ -132,7 +137,12 @@ defmodule SimpleshopTheme.Media do
|
||||
|
||||
"""
|
||||
def get_header do
|
||||
Repo.one(from i in ImageSchema, where: i.image_type == "header", order_by: [desc: i.inserted_at], limit: 1)
|
||||
Repo.one(
|
||||
from i in ImageSchema,
|
||||
where: i.image_type == "header",
|
||||
order_by: [desc: i.inserted_at],
|
||||
limit: 1
|
||||
)
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
||||
@@ -46,7 +46,8 @@ defmodule SimpleshopTheme.Media.Image do
|
||||
defp detect_svg(changeset) do
|
||||
content_type = get_change(changeset, :content_type)
|
||||
|
||||
if content_type == "image/svg+xml" or String.ends_with?(get_change(changeset, :filename) || "", ".svg") do
|
||||
if content_type == "image/svg+xml" or
|
||||
String.ends_with?(get_change(changeset, :filename) || "", ".svg") do
|
||||
changeset
|
||||
|> put_change(:is_svg, true)
|
||||
|> maybe_store_svg_content()
|
||||
|
||||
@@ -23,7 +23,8 @@ defmodule SimpleshopTheme.Media.SVGRecolorer do
|
||||
|
||||
"""
|
||||
@spec recolor(String.t(), String.t()) :: String.t()
|
||||
def recolor(svg_content, target_color) when is_binary(svg_content) and is_binary(target_color) do
|
||||
def recolor(svg_content, target_color)
|
||||
when is_binary(svg_content) and is_binary(target_color) do
|
||||
svg_content
|
||||
|> recolor_fill_attributes(target_color)
|
||||
|> recolor_stroke_attributes(target_color)
|
||||
|
||||
@@ -163,9 +163,17 @@ defmodule SimpleshopTheme.Mockups.Generator do
|
||||
hoodie: %{blueprint_id: nil, print_provider_id: nil, search_term: "Pullover Hoodie"},
|
||||
tote: %{blueprint_id: nil, print_provider_id: nil, search_term: "Cotton Tote Bag"},
|
||||
mug: %{blueprint_id: nil, print_provider_id: nil, search_term: "Mug 11oz"},
|
||||
cushion: %{blueprint_id: nil, print_provider_id: nil, search_term: "Spun Polyester Square Pillow"},
|
||||
cushion: %{
|
||||
blueprint_id: nil,
|
||||
print_provider_id: nil,
|
||||
search_term: "Spun Polyester Square Pillow"
|
||||
},
|
||||
blanket: %{blueprint_id: nil, print_provider_id: nil, search_term: "Sherpa Fleece Blanket"},
|
||||
notebook: %{blueprint_id: nil, print_provider_id: nil, search_term: "Hardcover Journal Matte"},
|
||||
notebook: %{
|
||||
blueprint_id: nil,
|
||||
print_provider_id: nil,
|
||||
search_term: "Hardcover Journal Matte"
|
||||
},
|
||||
phone_case: %{blueprint_id: nil, print_provider_id: nil, search_term: "Tough Phone Cases"},
|
||||
laptop_sleeve: %{blueprint_id: nil, print_provider_id: nil, search_term: "Laptop Sleeve"}
|
||||
}
|
||||
@@ -253,12 +261,12 @@ defmodule SimpleshopTheme.Mockups.Generator do
|
||||
"""
|
||||
def calculate_cover_scale(artwork_width, artwork_height, placeholder_width, placeholder_height)
|
||||
when is_number(artwork_width) and is_number(artwork_height) and
|
||||
is_number(placeholder_width) and is_number(placeholder_height) and
|
||||
artwork_width > 0 and artwork_height > 0 and
|
||||
placeholder_width > 0 and placeholder_height > 0 do
|
||||
is_number(placeholder_width) and is_number(placeholder_height) and
|
||||
artwork_width > 0 and artwork_height > 0 and
|
||||
placeholder_width > 0 and placeholder_height > 0 do
|
||||
# For cover: use the larger scale to ensure full coverage
|
||||
width_scale = 1.0
|
||||
height_scale = (placeholder_height * artwork_width) / (artwork_height * placeholder_width)
|
||||
height_scale = placeholder_height * artwork_width / (artwork_height * placeholder_width)
|
||||
max(width_scale, height_scale)
|
||||
end
|
||||
|
||||
@@ -267,21 +275,36 @@ defmodule SimpleshopTheme.Mockups.Generator do
|
||||
@doc """
|
||||
Create a product with the uploaded artwork.
|
||||
"""
|
||||
def create_product(shop_id, product_def, image_id, image_width, image_height, blueprint_id, print_provider_id, variants) do
|
||||
def create_product(
|
||||
shop_id,
|
||||
product_def,
|
||||
image_id,
|
||||
image_width,
|
||||
image_height,
|
||||
blueprint_id,
|
||||
print_provider_id,
|
||||
variants
|
||||
) do
|
||||
# Get the first variant for simplicity (typically a standard size/color)
|
||||
variant = hd(variants)
|
||||
variant_id = variant["id"]
|
||||
|
||||
# Get placeholder info
|
||||
placeholders = variant["placeholders"] || []
|
||||
front_placeholder = Enum.find(placeholders, fn p -> p["position"] == "front" end) || hd(placeholders)
|
||||
|
||||
front_placeholder =
|
||||
Enum.find(placeholders, fn p -> p["position"] == "front" end) || hd(placeholders)
|
||||
|
||||
# Extract placeholder dimensions and calculate cover scale
|
||||
placeholder_width = front_placeholder["width"]
|
||||
placeholder_height = front_placeholder["height"]
|
||||
scale = calculate_cover_scale(image_width, image_height, placeholder_width, placeholder_height)
|
||||
|
||||
IO.puts(" Scale calculation: artwork #{image_width}x#{image_height}, placeholder #{placeholder_width}x#{placeholder_height} -> scale #{Float.round(scale, 3)}")
|
||||
scale =
|
||||
calculate_cover_scale(image_width, image_height, placeholder_width, placeholder_height)
|
||||
|
||||
IO.puts(
|
||||
" Scale calculation: artwork #{image_width}x#{image_height}, placeholder #{placeholder_width}x#{placeholder_height} -> scale #{Float.round(scale, 3)}"
|
||||
)
|
||||
|
||||
product_data = %{
|
||||
title: product_def.name,
|
||||
@@ -439,7 +462,17 @@ defmodule SimpleshopTheme.Mockups.Generator do
|
||||
image_height = upload["height"],
|
||||
_ = IO.puts(" Artwork uploaded (ID: #{image_id}, #{image_width}x#{image_height})"),
|
||||
_ = IO.puts(" Creating product..."),
|
||||
{:ok, product} <- create_product(shop_id, product_def, image_id, image_width, image_height, blueprint_id, provider_id, variants),
|
||||
{:ok, product} <-
|
||||
create_product(
|
||||
shop_id,
|
||||
product_def,
|
||||
image_id,
|
||||
image_width,
|
||||
image_height,
|
||||
blueprint_id,
|
||||
provider_id,
|
||||
variants
|
||||
),
|
||||
product_id = product["id"],
|
||||
mockup_urls = extract_mockup_urls(product),
|
||||
_ = IO.puts(" Product created (ID: #{product_id})"),
|
||||
|
||||
@@ -287,14 +287,17 @@ defmodule SimpleshopTheme.Products do
|
||||
|
||||
if MapSet.size(removed_ids) > 0 do
|
||||
from(v in ProductVariant,
|
||||
where: v.product_id == ^product_id and v.provider_variant_id in ^MapSet.to_list(removed_ids)
|
||||
where:
|
||||
v.product_id == ^product_id and v.provider_variant_id in ^MapSet.to_list(removed_ids)
|
||||
)
|
||||
|> Repo.delete_all()
|
||||
end
|
||||
|
||||
# Upsert incoming variants
|
||||
Enum.map(variants, fn variant_data ->
|
||||
provider_variant_id = variant_data[:provider_variant_id] || variant_data["provider_variant_id"]
|
||||
provider_variant_id =
|
||||
variant_data[:provider_variant_id] || variant_data["provider_variant_id"]
|
||||
|
||||
attrs = Map.put(variant_data, :product_id, product_id)
|
||||
|
||||
case get_variant_by_provider(product_id, provider_variant_id) do
|
||||
|
||||
@@ -88,7 +88,8 @@ defmodule SimpleshopTheme.Products.ProductVariant do
|
||||
Formats the options as a human-readable title.
|
||||
E.g., %{"Size" => "Large", "Color" => "Blue"} -> "Large / Blue"
|
||||
"""
|
||||
def options_title(%__MODULE__{options: options}) when is_map(options) and map_size(options) > 0 do
|
||||
def options_title(%__MODULE__{options: options})
|
||||
when is_map(options) and map_size(options) > 0 do
|
||||
options
|
||||
|> Map.values()
|
||||
|> Enum.join(" / ")
|
||||
|
||||
@@ -93,7 +93,10 @@ defmodule SimpleshopTheme.Settings.ThemeSettings do
|
||||
])
|
||||
|> validate_required([:mood, :typography, :shape, :density])
|
||||
|> validate_inclusion(:mood, ~w(neutral warm cool dark))
|
||||
|> validate_inclusion(:typography, ~w(clean editorial modern classic friendly minimal impulse))
|
||||
|> validate_inclusion(
|
||||
:typography,
|
||||
~w(clean editorial modern classic friendly minimal impulse)
|
||||
)
|
||||
|> validate_inclusion(:shape, ~w(sharp soft round pill))
|
||||
|> validate_inclusion(:density, ~w(spacious balanced compact))
|
||||
|> validate_inclusion(:grid_columns, ~w(2 3 4))
|
||||
@@ -101,8 +104,14 @@ defmodule SimpleshopTheme.Settings.ThemeSettings do
|
||||
|> validate_inclusion(:logo_mode, ~w(text-only logo-text logo-only))
|
||||
|> validate_number(:logo_size, greater_than_or_equal_to: 24, less_than_or_equal_to: 120)
|
||||
|> validate_number(:header_zoom, greater_than_or_equal_to: 100, less_than_or_equal_to: 200)
|
||||
|> validate_number(:header_position_x, greater_than_or_equal_to: 0, less_than_or_equal_to: 100)
|
||||
|> validate_number(:header_position_y, greater_than_or_equal_to: 0, less_than_or_equal_to: 100)
|
||||
|> validate_number(:header_position_x,
|
||||
greater_than_or_equal_to: 0,
|
||||
less_than_or_equal_to: 100
|
||||
)
|
||||
|> validate_number(:header_position_y,
|
||||
greater_than_or_equal_to: 0,
|
||||
less_than_or_equal_to: 100
|
||||
)
|
||||
|> validate_inclusion(:layout_width, ~w(contained wide full))
|
||||
|> validate_inclusion(:card_shadow, ~w(none sm md lg))
|
||||
|> validate_inclusion(:font_size, ~w(small medium large))
|
||||
|
||||
@@ -234,5 +234,4 @@ defmodule SimpleshopTheme.Theme.Fonts do
|
||||
""
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -67,7 +67,8 @@ defmodule SimpleshopTheme.Theme.PreviewData do
|
||||
%{
|
||||
rating: 5,
|
||||
title: "Absolutely beautiful",
|
||||
body: "The quality exceeded my expectations. The colours are vibrant and the paper feels premium. It's now pride of place in my living room.",
|
||||
body:
|
||||
"The quality exceeded my expectations. The colours are vibrant and the paper feels premium. It's now pride of place in my living room.",
|
||||
author: "Sarah M.",
|
||||
date: "2 weeks ago",
|
||||
verified: true
|
||||
@@ -75,7 +76,8 @@ defmodule SimpleshopTheme.Theme.PreviewData do
|
||||
%{
|
||||
rating: 4,
|
||||
title: "Great gift",
|
||||
body: "Bought this as a gift and it arrived beautifully packaged. Fast shipping too. Would definitely order again.",
|
||||
body:
|
||||
"Bought this as a gift and it arrived beautifully packaged. Fast shipping too. Would definitely order again.",
|
||||
author: "James T.",
|
||||
date: "1 month ago",
|
||||
verified: true
|
||||
@@ -90,13 +92,33 @@ defmodule SimpleshopTheme.Theme.PreviewData do
|
||||
"""
|
||||
def about_content do
|
||||
[
|
||||
%{type: :lead, text: "I'm Emma, a nature photographer based in the UK. What started as weekend walks with my camera has grown into something I never expected – a little shop where I can share my favourite captures with others."},
|
||||
%{type: :paragraph, text: "Every design in this shop comes from my own photography. Whether it's early morning mist over the hills, autumn leaves in the local woods, or the quiet beauty of wildflower meadows, I'm drawn to the peaceful moments that nature offers."},
|
||||
%{type: :paragraph, text: "I work with quality print partners to bring these images to life on products you can actually use and enjoy – from art prints for your walls to mugs for your morning tea."},
|
||||
%{
|
||||
type: :lead,
|
||||
text:
|
||||
"I'm Emma, a nature photographer based in the UK. What started as weekend walks with my camera has grown into something I never expected – a little shop where I can share my favourite captures with others."
|
||||
},
|
||||
%{
|
||||
type: :paragraph,
|
||||
text:
|
||||
"Every design in this shop comes from my own photography. Whether it's early morning mist over the hills, autumn leaves in the local woods, or the quiet beauty of wildflower meadows, I'm drawn to the peaceful moments that nature offers."
|
||||
},
|
||||
%{
|
||||
type: :paragraph,
|
||||
text:
|
||||
"I work with quality print partners to bring these images to life on products you can actually use and enjoy – from art prints for your walls to mugs for your morning tea."
|
||||
},
|
||||
%{type: :heading, text: "Quality you can trust"},
|
||||
%{type: :paragraph, text: "I've carefully chosen print partners who share my commitment to quality. Every product is made to order using premium materials and printing techniques that ensure vibrant colours and lasting quality."},
|
||||
%{
|
||||
type: :paragraph,
|
||||
text:
|
||||
"I've carefully chosen print partners who share my commitment to quality. Every product is made to order using premium materials and printing techniques that ensure vibrant colours and lasting quality."
|
||||
},
|
||||
%{type: :heading, text: "Printed sustainably"},
|
||||
%{type: :paragraph, text: "Because each item is printed on demand, there's no waste from unsold stock. My print partners use eco-friendly inks where possible, and products are shipped directly to you to minimise unnecessary handling."},
|
||||
%{
|
||||
type: :paragraph,
|
||||
text:
|
||||
"Because each item is printed on demand, there's no waste from unsold stock. My print partners use eco-friendly inks where possible, and products are shipped directly to you to minimise unnecessary handling."
|
||||
},
|
||||
%{type: :closing, text: "Thank you for visiting. It means a lot that you're here."}
|
||||
]
|
||||
end
|
||||
@@ -427,42 +449,48 @@ defmodule SimpleshopTheme.Theme.PreviewData do
|
||||
%{
|
||||
id: "1",
|
||||
author: "Sarah M.",
|
||||
content: "The print quality is absolutely stunning - colours are exactly as shown online. My living room looks so much better now!",
|
||||
content:
|
||||
"The print quality is absolutely stunning - colours are exactly as shown online. My living room looks so much better now!",
|
||||
rating: 5,
|
||||
date: "2025-01-15"
|
||||
},
|
||||
%{
|
||||
id: "2",
|
||||
author: "James L.",
|
||||
content: "Bought the forest hoodie as a gift. The packaging was lovely and the quality exceeded expectations. Will order again!",
|
||||
content:
|
||||
"Bought the forest hoodie as a gift. The packaging was lovely and the quality exceeded expectations. Will order again!",
|
||||
rating: 5,
|
||||
date: "2025-01-10"
|
||||
},
|
||||
%{
|
||||
id: "3",
|
||||
author: "Emily R.",
|
||||
content: "My new favourite mug! I love sipping my morning tea while looking at that beautiful fern design.",
|
||||
content:
|
||||
"My new favourite mug! I love sipping my morning tea while looking at that beautiful fern design.",
|
||||
rating: 5,
|
||||
date: "2025-01-05"
|
||||
},
|
||||
%{
|
||||
id: "4",
|
||||
author: "Michael T.",
|
||||
content: "The tote bag is so sturdy - I use it for everything now. Great print quality that hasn't faded at all.",
|
||||
content:
|
||||
"The tote bag is so sturdy - I use it for everything now. Great print quality that hasn't faded at all.",
|
||||
rating: 5,
|
||||
date: "2024-12-28"
|
||||
},
|
||||
%{
|
||||
id: "5",
|
||||
author: "Lisa K.",
|
||||
content: "The night sky blanket is gorgeous and so cosy. Perfect for film nights on the sofa. Highly recommend!",
|
||||
content:
|
||||
"The night sky blanket is gorgeous and so cosy. Perfect for film nights on the sofa. Highly recommend!",
|
||||
rating: 5,
|
||||
date: "2024-12-20"
|
||||
},
|
||||
%{
|
||||
id: "6",
|
||||
author: "David P.",
|
||||
content: "Ordered several prints for my new flat. They arrived well packaged and look amazing on the wall.",
|
||||
content:
|
||||
"Ordered several prints for my new flat. They arrived well packaged and look amazing on the wall.",
|
||||
rating: 5,
|
||||
date: "2024-12-15"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user