Compare commits

..

5 Commits

Author SHA1 Message Date
empty
e4015b750d docs: v1.1.0 发布元数据更新(8 种语言版本说明)
- APP_STORE_METADATA.md: 版本号更新、新功能描述、发布检查清单
- APP_STORE_METADATA_I18N.md: 8 种语言 What's New
  (zh-Hans, zh-Hant, en, es, ar, fr, ja, ko)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-08 01:23:41 +08:00
empty
d27c119b05 chore: 版本号更新至 1.1.0 (1)
MARKETING_VERSION: 1.0.1/1.0.2 → 1.1.0
CURRENT_PROJECT_VERSION: 2/3 → 1

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-08 01:12:38 +08:00
empty
4dc6259a29 fix: 修复 ResultView Live Photo 预览宽度铺满问题
PHLivePhotoView 无 intrinsic content size,SwiftUI 的
.aspectRatio() 对 UIViewRepresentable 无效。
改用 Color.clear + aspectRatio 撑出正确比例容器,
再用 .overlay 放入 Live Photo 预览。
同时移除 .frame(maxWidth: .infinity) 避免强制撑满。

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-08 00:56:12 +08:00
empty
88af6b6682 fix: 修复错误统计中 UNKNOWN 错误码问题
三处修复:
1. Analytics.logError() — 从通用 Error 提取 NSError domain:code,
   不再一律记录为 UNKNOWN
2. AppState — 通用 catch 已构造 AppError(LPB-901),改用
   logAppError 记录,确保错误码正确归类
3. HomeView — 视频导入错误包装为 AppError(IMP-001),
   添加 import LivePhotoCore

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-08 00:49:13 +08:00
empty
2f6c2d9557 fix: 修复导出诊断包点击后黑屏问题
将 .sheet(isPresented:) + if let 改为 .sheet(item:) 模式,
消除 feedbackPackageURL 与 showingShareSheet 的状态时序竞争。

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-08 00:43:43 +08:00
8 changed files with 253 additions and 34 deletions

View File

@@ -11,7 +11,7 @@
| **应用名称** | Live Photo Studio |
| **副标题** | 视频一键转动态壁纸 |
| **Bundle ID** | xyz.let5see.livephotomaker |
| **版本号** | 1.0 |
| **版本号** | 1.1.0 |
| **Build 号** | 1 |
| **分类** | 主类别: Photo & Video / 次类别: Utilities |
| **年龄分级** | 4+ |
@@ -34,13 +34,14 @@ Live Photo Studio 是一款简单易用的动态壁纸制作工具,让你的
【一键转换】
• 从相册选择视频,一键转换为 Live Photo
智能时长裁剪,自动适配系统要求
支持最长 5 秒视频,创作更自由
• 支持各种视频格式MP4、MOV、H.264、HEVC
【精准编辑】
• 多种比例模板iPhone 锁屏、全面屏、4:3 等
• 双指缩放和拖拽,精准裁剪画面
滑块选择封面帧,预览实时更新
自定义封面照片,精准选择关键帧
• 编辑参数预设,一键应用常用配置
【AI 超分辨率】
• 使用 AI 技术提升封面画质
@@ -52,6 +53,10 @@ Live Photo Studio 是一款简单易用的动态壁纸制作工具,让你的
• 自动转换为最兼容格式
• 支持 4K、HDR、HEVC 等高规格视频
【智能管理】
• iCloud 同步最近作品,多设备无缝切换
• 作品历史记录,随时回顾创作
【设置引导】
• 详细的壁纸设置教程
• 常见问题解答
@@ -77,6 +82,26 @@ Live Photo,动态壁纸,锁屏壁纸,视频转换,AI增强,照片,壁纸,动图,
## 新功能(版本说明)
### 1.1.0 版本
```
更强大的功能,更流畅的体验!
【新功能】
• 视频时长放宽至 5 秒,创作更自由
• 自定义封面照片,精准选择关键帧
• 编辑参数预设,一键应用常用配置
• iCloud 同步最近作品,多设备无缝切换
【体验优化】
• 首页入场动画更流畅
• 触觉反馈增强操作体验
• 视觉一致性全面提升
【稳定性】
• 修复 2 个崩溃问题
• 30+ 项稳定性优化
```
### 1.0 版本
```
Live Photo Studio 正式发布!
@@ -193,20 +218,32 @@ https://let5sne.github.io/xyz.let5see.livephotomaker/terms.html
## 版权信息
```
© 2025 let5see.xyz. All rights reserved.
© 2025-2026 let5see.xyz. All rights reserved.
```
---
## 上架检查清单
### v1.1.0 发布检查
#### 版本准备
- [x] 版本号已更新为 1.1.0 (1)
- [x] 代码审查已完成38项全部修复
- [x] 模拟器构建通过
- [ ] 9种语言版本说明已准备
- [ ] 截图需要更新(新增预设管理、自定义封面等功能截图)
- [ ] Archive 构建
- [ ] TestFlight 内部测试
- [ ] 提交审核
### 开发者账号
- [ ] Apple Developer Program 已加入($99/年)
- [ ] App Store Connect 账号已创建
### 应用配置
- [x] Bundle ID: xyz.let5see.livephotomaker
- [x] 版本号: 1.0
- [x] 版本号: 1.1.0
- [x] 应用图标: 1024x1024
- [x] 权限说明文案
- [x] 隐私政策(应用内)
@@ -220,6 +257,10 @@ https://let5sne.github.io/xyz.let5see.livephotomaker/terms.html
### 需要准备
- [ ] iPhone 截图(至少 6.7" 和 6.5"
- [ ] 预设管理功能截图
- [ ] 自定义封面功能截图
- [ ] 5秒视频支持展示
- [ ] iCloud 同步展示
- [ ] iPad 截图(如果支持 iPad
### 构建上传

View File

@@ -428,6 +428,168 @@ Live Photo Studio 정식 출시!
---
**创建时间**: 2026-01-10
**版本**: 1.0.1
## 🆕 v1.1.0 版本说明What's New
### zh-Hans (简体中文)
```
更强大的功能,更流畅的体验!
【新功能】
• 视频时长放宽至 5 秒,创作更自由
• 支持从相册导入自定义封面照片
• 编辑参数预设管理,一键应用常用配置
• iCloud 同步最近作品,多设备无缝切换
【体验优化】
• 首页入场动画更流畅,最近作品卡片尺寸增大
• 新增触觉反馈,操作更有手感
• 视觉一致性全面提升
【稳定性】
• 修复 2 个可能导致崩溃的问题
• 30+ 项稳定性和体验优化
```
### zh-Hant (繁體中文)
```
更強大的功能,更流暢的體驗!
【新功能】
• 影片時長擴展至 5 秒,創作更自由
• 支援從相簿匯入自訂封面照片
• 編輯參數預設管理,一鍵套用常用配置
• iCloud 同步最近作品,多裝置無縫切換
【體驗優化】
• 首頁入場動畫更流暢,最近作品卡片尺寸增大
• 新增觸覺回饋,操作更有手感
• 視覺一致性全面提升
【穩定性】
• 修復 2 個可能導致當機的問題
• 30+ 項穩定性和體驗優化
```
### en (English)
```
More powerful features, smoother experience!
New Features
- Extended video duration to 5 seconds for more creative freedom
- Import custom cover photos from your library
- Editing preset management: save and reuse your favorite configurations
- iCloud sync for recent works across all your devices
Experience Improvements
- Smoother home screen animation with larger recent works cards
- Added haptic feedback for key operations
- Enhanced visual consistency throughout the app
Stability
- Fixed 2 potential crash issues
- 30+ stability and experience improvements
```
### es (Español)
```
Funciones mas potentes, experiencia mas fluida!
Nuevas Funciones
- Duracion de video extendida a 5 segundos para mayor libertad creativa
- Importa fotos de portada personalizadas desde tu biblioteca
- Gestion de ajustes preestablecidos: guarda y reutiliza tus configuraciones favoritas
- Sincronizacion iCloud de trabajos recientes en todos tus dispositivos
Mejoras de Experiencia
- Animacion de inicio mas fluida con tarjetas de trabajos recientes mas grandes
- Retroalimentacion haptica para operaciones clave
- Consistencia visual mejorada en toda la aplicacion
Estabilidad
- Corregidos 2 problemas potenciales de bloqueo
- 30+ mejoras de estabilidad y experiencia
```
### ar (العربية)
```
ميزات أقوى، تجربة أكثر سلاسة!
ميزات جديدة
- مدة الفيديو ممتدة إلى 5 ثوانٍ لمزيد من الحرية الإبداعية
- استيراد صور غلاف مخصصة من مكتبة الصور
- إدارة الإعدادات المسبقة: احفظ وأعد استخدام تكويناتك المفضلة
- مزامنة iCloud للأعمال الأخيرة عبر جميع أجهزتك
تحسينات التجربة
- رسوم دخول أكثر سلاسة مع بطاقات أعمال أكبر
- ردود فعل لمسية للعمليات الرئيسية
- اتساق بصري محسّن في جميع أنحاء التطبيق
الاستقرار
- إصلاح مشكلتين قد تؤديان إلى تعطل التطبيق
- أكثر من 30 تحسينًا للاستقرار والتجربة
```
### fr (Français)
```
Des fonctionnalites plus puissantes, une experience plus fluide !
Nouvelles fonctionnalites
- Duree video etendue a 5 secondes pour plus de liberte creative
- Importation de photos de couverture personnalisees depuis votre bibliotheque
- Gestion des prereglages : enregistrez et reutilisez vos configurations favorites
- Synchronisation iCloud des creations recentes sur tous vos appareils
Ameliorations de l'experience
- Animation d'entree plus fluide avec des cartes de projets agrandies
- Retour haptique pour les operations cles
- Coherence visuelle renforcee dans toute l'application
Stabilite
- Correction de 2 problemes pouvant entrainer des plantages
- Plus de 30 ameliorations de stabilite et d'experience
```
### ja (日本語)
```
より強力な機能、よりスムーズな体験!
新機能
- 動画の長さを5秒まで拡張、より自由な創作が可能に
- フォトライブラリからカスタムカバー写真をインポート
- 編集プリセット管理:よく使う設定を保存してワンタップで再利用
- iCloud同期で全デバイスの最近の作品を共有
体験の改善
- ホーム画面のアニメーションを最適化、作品カードを拡大
- 主要操作に触覚フィードバックを追加
- アプリ全体のビジュアル一貫性を向上
安定性
- クラッシュの可能性がある2つの問題を修正
- 30件以上の安定性と体験の改善
```
### ko (한국어)
```
더 강력한 기능, 더 부드러운 경험!
새로운 기능
- 동영상 길이 5초로 확장, 더 자유로운 창작 가능
- 사진 보관함에서 커스텀 커버 사진 가져오기
- 편집 프리셋 관리: 자주 쓰는 설정 저장 후 한 번의 탭으로 재사용
- iCloud 동기화로 모든 기기에서 최근 작품 공유
경험 개선
- 홈 화면 애니메이션 최적화, 작품 카드 크기 확대
- 주요 작업에 햅틱 피드백 추가
- 앱 전체의 시각적 일관성 향상
안정성
- 충돌 가능성이 있는 2가지 문제 수정
- 30개 이상의 안정성 및 경험 개선
```
---**最后更新**: 2026-02-08
**版本**: 1.1.0
**状态**: ✅ 已完成,可直接复制到 App Store Connect

View File

@@ -414,7 +414,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = Y976PBNGA8;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
@@ -430,7 +430,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.1;
MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = xyz.let5see.livephotomaker;
PRODUCT_NAME = "$(TARGET_NAME)";
STRING_CATALOG_GENERATE_SYMBOLS = YES;
@@ -449,7 +449,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = Y976PBNGA8;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
@@ -465,7 +465,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.1;
MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = xyz.let5see.livephotomaker;
PRODUCT_NAME = "$(TARGET_NAME)";
STRING_CATALOG_GENERATE_SYMBOLS = YES;
@@ -483,11 +483,11 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = Y976PBNGA8;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
MARKETING_VERSION = 1.0.1;
MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = xyz.let5see.livephotomakerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
STRING_CATALOG_GENERATE_SYMBOLS = NO;
@@ -505,11 +505,11 @@
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = Y976PBNGA8;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
MARKETING_VERSION = 1.0.1;
MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = xyz.let5see.livephotomakerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
STRING_CATALOG_GENERATE_SYMBOLS = NO;
@@ -526,10 +526,10 @@
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = Y976PBNGA8;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0.1;
MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = xyz.let5see.livephotomakerUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
STRING_CATALOG_GENERATE_SYMBOLS = NO;
@@ -546,10 +546,10 @@
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = Y976PBNGA8;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0.1;
MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = xyz.let5see.livephotomakerUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
STRING_CATALOG_GENERATE_SYMBOLS = NO;

View File

@@ -133,8 +133,12 @@ final class Analytics {
//
errorStats.record(code: appError.code, stage: appError.stage?.rawValue)
} else {
//
let code = "UNKNOWN"
//
let nsError = error as NSError
let code = "\(nsError.domain):\(nsError.code)"
params["code"] = code
params["domain"] = nsError.domain
params["nsErrorCode"] = nsError.code
errorStats.record(code: code, stage: nil)
}

View File

@@ -168,13 +168,14 @@ final class AppState {
}
return nil
} catch {
let appError = AppError(code: "LPB-901", message: "未知错误", underlyingErrorDescription: error.localizedDescription, suggestedActions: ["重试"])
await MainActor.run {
self.isProcessing = false
self.processingError = AppError(code: "LPB-901", message: "未知错误", underlyingErrorDescription: error.localizedDescription, suggestedActions: ["重试"])
self.processingError = appError
self.currentWorkId = nil
self.currentProcessingTask = nil
}
Analytics.shared.logError(.buildLivePhotoFail, error: error)
Analytics.shared.logAppError(.buildLivePhotoFail, appError: appError)
return nil
}
}

View File

@@ -9,6 +9,7 @@ import SwiftUI
import PhotosUI
import AVKit
import Photos
import LivePhotoCore
struct HomeView: View {
@Environment(AppState.self) private var appState
@@ -279,7 +280,12 @@ struct HomeView: View {
errorMessage = String(format: format, error.localizedDescription)
isLoading = false
selectedItem = nil
Analytics.shared.logError(.importVideoFail, error: error)
let appError = AppError(
code: "IMP-001",
message: "视频导入失败",
underlyingErrorDescription: error.localizedDescription
)
Analytics.shared.logAppError(.importVideoFail, appError: appError)
}
}
}

View File

@@ -83,13 +83,16 @@ struct ResultView: View {
let photoSize = livePhoto.size
let ratio = photoSize.width / max(photoSize.height, 1)
SoftCard(padding: DesignTokens.Spacing.md) {
LivePhotoPreviewView(livePhoto: livePhoto)
// PHLivePhotoView intrinsic size Color.clear
Color.clear
.aspectRatio(ratio, contentMode: .fit)
.frame(maxHeight: 360)
.overlay {
LivePhotoPreviewView(livePhoto: livePhoto)
}
.clipShape(RoundedRectangle(cornerRadius: DesignTokens.Radius.lg))
.accessibilityLabel(String(localized: "result.livePhotoPreview.accessibilityLabel"))
}
.frame(maxWidth: .infinity)
}
Text(String(localized: "result.livePhotoPreview.hint"))

View File

@@ -13,8 +13,7 @@ struct SettingsView: View {
@State private var cacheSize: String = String(localized: "common.calculating")
@State private var showingClearCacheAlert = false
@State private var showingClearRecentWorksAlert = false
@State private var feedbackPackageURL: URL?
@State private var showingShareSheet = false
@State private var feedbackPackageURL: IdentifiableURL?
@State private var showingLanguageChangeAlert = false
@State private var showingFeedbackConfirmAlert = false
@State private var pendingLanguage: LanguageManager.Language?
@@ -182,10 +181,8 @@ struct SettingsView: View {
} message: {
Text(String(localized: "settings.feedbackConfirmMessage"))
}
.sheet(isPresented: $showingShareSheet) {
if let url = feedbackPackageURL {
ShareSheet(activityItems: [url])
}
.sheet(item: $feedbackPackageURL) { item in
ShareSheet(activityItems: [item.url])
}
}
@@ -299,8 +296,7 @@ struct SettingsView: View {
let url = await createFeedbackPackage()
await MainActor.run {
if let url {
feedbackPackageURL = url
showingShareSheet = true
feedbackPackageURL = IdentifiableURL(url: url)
}
}
}
@@ -425,6 +421,12 @@ extension PHAuthorizationStatus: @retroactive CustomStringConvertible {
}
}
// MARK: - Identifiable URL Wrapper
struct IdentifiableURL: Identifiable {
let id = UUID()
let url: URL
}
// MARK: - Share Sheet
struct ShareSheet: UIViewControllerRepresentable {
let activityItems: [Any]