84 public IReadOnlyList<PhotoInfo>
Gallery {
get;
private set; } = [];
93 public IReadOnlyList<PhotoInfo>
AllPhotos {
get;
private set; } = [];
391 var raw =
Config?.CeremonyNote ??
"";
392 if (
string.IsNullOrWhiteSpace(raw))
return "";
395 return Markdown.ToHtml(raw,
new MarkdownPipelineBuilder().UseAdvancedExtensions().Build());
407 string.Equals(
Config?.CeremonyNoteFormat,
"Html", StringComparison.OrdinalIgnoreCase);
421 if (
Config is
null)
return "";
422 if (!
string.IsNullOrWhiteSpace(
Config.HeroImageFileName))
440 if (
Config is
null ||
string.IsNullOrWhiteSpace(
Config.RoadMapFileName))
return "";
465 : $
"{CoupleName} 청첩장";
476 ? Config.OgDescription
477 : $
"{WeddingDate:yyyy년 MM월 dd일} {VenueName}에서 함께해 주세요.";
491 if (
Config is
null)
return "";
493 var fn = !
string.IsNullOrWhiteSpace(
Config.OgImageFileName)
494 ? Config.OgImageFileName
495 :
Config.HeroImageFileName;
496 return string.IsNullOrWhiteSpace(fn) ?
"" :
_photos.GetHeroUrl(
Config.Slug, fn);
509 ? Config.ThankYouOgTitle
510 : $
"{CoupleName} 감사 인사";
521 ? Config.ThankYouOgDescription
522 : $
"{WeddingDate:yyyy년 MM월 dd일} {VenueName}에서의 결혼식을 마쳤습니다. 함께해 주셔서 감사합니다.";
536 if (
Config is
null)
return "";
537 var fn = !
string.IsNullOrWhiteSpace(
Config.ThankYouOgImageFileName)
538 ? Config.ThankYouOgImageFileName
539 :
Config.HeroImageFileName;
540 return string.IsNullOrWhiteSpace(fn) ?
"" :
_photos.GetHeroUrl(
Config.Slug, fn);
556 if (
Config is
null ||
string.IsNullOrWhiteSpace(
Config.MusicFileName))
return "";
588 DesignSettings.MusicButtonPlacement.HasDesktop ||
DesignSettings.MusicButtonPlacement.HasMobile;
725 DesignSettings.HeroPlacement.InviteTop.HasDesktopCustomPosition ||
DesignSettings.HeroPlacement.InviteTop.HasMobileCustomPosition;
735 DesignSettings.HeroPlacement.InviteBottom.HasDesktopCustomPosition ||
DesignSettings.HeroPlacement.InviteBottom.HasMobileCustomPosition;
893 if (explicitPhoto is not
null)
895 return explicitPhoto;
898 return chapterIndex >= 0 && chapterIndex < AllPhotos.Count
935 public async Task
LoadAsync(
string slug, CancellationToken ct =
default)
941 var all = await
_photos.GetGalleryAsync(slug, ct).ConfigureAwait(
false);
944 Gallery = sorted.Take(10).ToList();
980 private static List<PhotoInfo>
ApplyGalleryOrder(IReadOnlyList<PhotoInfo> photos, IReadOnlyList<string> order)
983 .Select((fileName, index) =>
new { fileName, index })
984 .GroupBy(x => x.fileName, StringComparer.OrdinalIgnoreCase)
985 .ToDictionary(x => x.Key, x => x.First().index, StringComparer.OrdinalIgnoreCase);
988 .OrderBy(p => orderMap.TryGetValue(p.FileName, out var index) ? index :
int.MaxValue)
989 .ThenByDescending(p => p.LastModified)
990 .ThenByDescending(p => p.FileName)
1020 if (
string.IsNullOrWhiteSpace(value))
1025 var key = value.Trim();
1027 string.Equals(p.FileName, key, StringComparison.OrdinalIgnoreCase) ||
1028 string.Equals(p.Url, key, StringComparison.OrdinalIgnoreCase) ||
1029 string.Equals(p.ThumbUrl, key, StringComparison.OrdinalIgnoreCase) ||
1030 p.Url.EndsWith(
"/" + key, StringComparison.OrdinalIgnoreCase) ||
1031 p.ThumbUrl.EndsWith(
"/" + key, StringComparison.OrdinalIgnoreCase));
1076 var normalized = value?.Trim().ToLowerInvariant();
1077 return !
string.IsNullOrWhiteSpace(normalized) && allowed.Contains(normalized) ? normalized : fallback;
1106 var parts =
new List<string>();
1107 if (position.HasDesktop)
1109 parts.Add($
"--w-drag-x:{ClampPercent(position.DesktopX):0.##}%;");
1110 parts.Add($
"--w-drag-y:{ClampPercent(position.DesktopY):0.##}%;");
1112 if (position.HasMobile)
1114 parts.Add($
"--w-drag-mobile-x:{ClampPercent(position.MobileX):0.##}%;");
1115 parts.Add($
"--w-drag-mobile-y:{ClampPercent(position.MobileY):0.##}%;");
1117 return string.Concat(parts);
1146 var parts =
new List<string>();
1149 parts.Add($
"--w-drag-x:{ClampPercent(placement.DesktopX):0.##}%;");
1150 parts.Add($
"--w-drag-y:{ClampPercent(placement.DesktopY):0.##}%;");
1154 parts.Add($
"--w-drag-mobile-x:{ClampPercent(placement.MobileX):0.##}%;");
1155 parts.Add($
"--w-drag-mobile-y:{ClampPercent(placement.MobileY):0.##}%;");
1157 return string.Concat(parts);
1184 private static double ClampPercent(
double? value) => Math.Clamp(value ?? 50, 0, 100);