Compare commits
5 Commits
c826689ee4
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4015b750d | ||
|
|
d27c119b05 | ||
|
|
4dc6259a29 | ||
|
|
88af6b6682 | ||
|
|
2f6c2d9557 |
@@ -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)
|
||||
|
||||
### 构建上传
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user