Compare commits
5 Commits
c826689ee4
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4015b750d | ||
|
|
d27c119b05 | ||
|
|
4dc6259a29 | ||
|
|
88af6b6682 | ||
|
|
2f6c2d9557 |
@@ -11,7 +11,7 @@
|
|||||||
| **应用名称** | Live Photo Studio |
|
| **应用名称** | Live Photo Studio |
|
||||||
| **副标题** | 视频一键转动态壁纸 |
|
| **副标题** | 视频一键转动态壁纸 |
|
||||||
| **Bundle ID** | xyz.let5see.livephotomaker |
|
| **Bundle ID** | xyz.let5see.livephotomaker |
|
||||||
| **版本号** | 1.0 |
|
| **版本号** | 1.1.0 |
|
||||||
| **Build 号** | 1 |
|
| **Build 号** | 1 |
|
||||||
| **分类** | 主类别: Photo & Video / 次类别: Utilities |
|
| **分类** | 主类别: Photo & Video / 次类别: Utilities |
|
||||||
| **年龄分级** | 4+ |
|
| **年龄分级** | 4+ |
|
||||||
@@ -34,13 +34,14 @@ Live Photo Studio 是一款简单易用的动态壁纸制作工具,让你的
|
|||||||
|
|
||||||
【一键转换】
|
【一键转换】
|
||||||
• 从相册选择视频,一键转换为 Live Photo
|
• 从相册选择视频,一键转换为 Live Photo
|
||||||
• 智能时长裁剪,自动适配系统要求
|
• 支持最长 5 秒视频,创作更自由
|
||||||
• 支持各种视频格式:MP4、MOV、H.264、HEVC
|
• 支持各种视频格式:MP4、MOV、H.264、HEVC
|
||||||
|
|
||||||
【精准编辑】
|
【精准编辑】
|
||||||
• 多种比例模板:iPhone 锁屏、全面屏、4:3 等
|
• 多种比例模板:iPhone 锁屏、全面屏、4:3 等
|
||||||
• 双指缩放和拖拽,精准裁剪画面
|
• 双指缩放和拖拽,精准裁剪画面
|
||||||
• 滑块选择封面帧,预览实时更新
|
• 自定义封面照片,精准选择关键帧
|
||||||
|
• 编辑参数预设,一键应用常用配置
|
||||||
|
|
||||||
【AI 超分辨率】
|
【AI 超分辨率】
|
||||||
• 使用 AI 技术提升封面画质
|
• 使用 AI 技术提升封面画质
|
||||||
@@ -52,6 +53,10 @@ Live Photo Studio 是一款简单易用的动态壁纸制作工具,让你的
|
|||||||
• 自动转换为最兼容格式
|
• 自动转换为最兼容格式
|
||||||
• 支持 4K、HDR、HEVC 等高规格视频
|
• 支持 4K、HDR、HEVC 等高规格视频
|
||||||
|
|
||||||
|
【智能管理】
|
||||||
|
• iCloud 同步最近作品,多设备无缝切换
|
||||||
|
• 作品历史记录,随时回顾创作
|
||||||
|
|
||||||
【设置引导】
|
【设置引导】
|
||||||
• 详细的壁纸设置教程
|
• 详细的壁纸设置教程
|
||||||
• 常见问题解答
|
• 常见问题解答
|
||||||
@@ -77,6 +82,26 @@ Live Photo,动态壁纸,锁屏壁纸,视频转换,AI增强,照片,壁纸,动图,
|
|||||||
|
|
||||||
## 新功能(版本说明)
|
## 新功能(版本说明)
|
||||||
|
|
||||||
|
### 1.1.0 版本
|
||||||
|
```
|
||||||
|
更强大的功能,更流畅的体验!
|
||||||
|
|
||||||
|
【新功能】
|
||||||
|
• 视频时长放宽至 5 秒,创作更自由
|
||||||
|
• 自定义封面照片,精准选择关键帧
|
||||||
|
• 编辑参数预设,一键应用常用配置
|
||||||
|
• iCloud 同步最近作品,多设备无缝切换
|
||||||
|
|
||||||
|
【体验优化】
|
||||||
|
• 首页入场动画更流畅
|
||||||
|
• 触觉反馈增强操作体验
|
||||||
|
• 视觉一致性全面提升
|
||||||
|
|
||||||
|
【稳定性】
|
||||||
|
• 修复 2 个崩溃问题
|
||||||
|
• 30+ 项稳定性优化
|
||||||
|
```
|
||||||
|
|
||||||
### 1.0 版本
|
### 1.0 版本
|
||||||
```
|
```
|
||||||
Live Photo Studio 正式发布!
|
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/年)
|
- [ ] Apple Developer Program 已加入($99/年)
|
||||||
- [ ] App Store Connect 账号已创建
|
- [ ] App Store Connect 账号已创建
|
||||||
|
|
||||||
### 应用配置
|
### 应用配置
|
||||||
- [x] Bundle ID: xyz.let5see.livephotomaker
|
- [x] Bundle ID: xyz.let5see.livephotomaker
|
||||||
- [x] 版本号: 1.0
|
- [x] 版本号: 1.1.0
|
||||||
- [x] 应用图标: 1024x1024
|
- [x] 应用图标: 1024x1024
|
||||||
- [x] 权限说明文案
|
- [x] 权限说明文案
|
||||||
- [x] 隐私政策(应用内)
|
- [x] 隐私政策(应用内)
|
||||||
@@ -220,6 +257,10 @@ https://let5sne.github.io/xyz.let5see.livephotomaker/terms.html
|
|||||||
|
|
||||||
### 需要准备
|
### 需要准备
|
||||||
- [ ] iPhone 截图(至少 6.7" 和 6.5")
|
- [ ] iPhone 截图(至少 6.7" 和 6.5")
|
||||||
|
- [ ] 预设管理功能截图
|
||||||
|
- [ ] 自定义封面功能截图
|
||||||
|
- [ ] 5秒视频支持展示
|
||||||
|
- [ ] iCloud 同步展示
|
||||||
- [ ] iPad 截图(如果支持 iPad)
|
- [ ] iPad 截图(如果支持 iPad)
|
||||||
|
|
||||||
### 构建上传
|
### 构建上传
|
||||||
|
|||||||
@@ -428,6 +428,168 @@ Live Photo Studio 정식 출시!
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**创建时间**: 2026-01-10
|
## 🆕 v1.1.0 版本说明(What's New)
|
||||||
**版本**: 1.0.1
|
|
||||||
|
### 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
|
**状态**: ✅ 已完成,可直接复制到 App Store Connect
|
||||||
|
|||||||
@@ -414,7 +414,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 2;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = Y976PBNGA8;
|
DEVELOPMENT_TEAM = Y976PBNGA8;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
@@ -430,7 +430,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.1;
|
MARKETING_VERSION = 1.1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = xyz.let5see.livephotomaker;
|
PRODUCT_BUNDLE_IDENTIFIER = xyz.let5see.livephotomaker;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
@@ -449,7 +449,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 2;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = Y976PBNGA8;
|
DEVELOPMENT_TEAM = Y976PBNGA8;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
@@ -465,7 +465,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0.1;
|
MARKETING_VERSION = 1.1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = xyz.let5see.livephotomaker;
|
PRODUCT_BUNDLE_IDENTIFIER = xyz.let5see.livephotomaker;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
@@ -483,11 +483,11 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 2;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = Y976PBNGA8;
|
DEVELOPMENT_TEAM = Y976PBNGA8;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
|
||||||
MARKETING_VERSION = 1.0.1;
|
MARKETING_VERSION = 1.1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = xyz.let5see.livephotomakerTests;
|
PRODUCT_BUNDLE_IDENTIFIER = xyz.let5see.livephotomakerTests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
||||||
@@ -505,11 +505,11 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 2;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = Y976PBNGA8;
|
DEVELOPMENT_TEAM = Y976PBNGA8;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
|
||||||
MARKETING_VERSION = 1.0.1;
|
MARKETING_VERSION = 1.1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = xyz.let5see.livephotomakerTests;
|
PRODUCT_BUNDLE_IDENTIFIER = xyz.let5see.livephotomakerTests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
||||||
@@ -526,10 +526,10 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 2;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = Y976PBNGA8;
|
DEVELOPMENT_TEAM = Y976PBNGA8;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0.1;
|
MARKETING_VERSION = 1.1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = xyz.let5see.livephotomakerUITests;
|
PRODUCT_BUNDLE_IDENTIFIER = xyz.let5see.livephotomakerUITests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
||||||
@@ -546,10 +546,10 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 2;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = Y976PBNGA8;
|
DEVELOPMENT_TEAM = Y976PBNGA8;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0.1;
|
MARKETING_VERSION = 1.1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = xyz.let5see.livephotomakerUITests;
|
PRODUCT_BUNDLE_IDENTIFIER = xyz.let5see.livephotomakerUITests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
||||||
|
|||||||
@@ -133,8 +133,12 @@ final class Analytics {
|
|||||||
// 记录到统计
|
// 记录到统计
|
||||||
errorStats.record(code: appError.code, stage: appError.stage?.rawValue)
|
errorStats.record(code: appError.code, stage: appError.stage?.rawValue)
|
||||||
} else {
|
} 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)
|
errorStats.record(code: code, stage: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -168,13 +168,14 @@ final class AppState {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
} catch {
|
} catch {
|
||||||
|
let appError = AppError(code: "LPB-901", message: "未知错误", underlyingErrorDescription: error.localizedDescription, suggestedActions: ["重试"])
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
self.isProcessing = false
|
self.isProcessing = false
|
||||||
self.processingError = AppError(code: "LPB-901", message: "未知错误", underlyingErrorDescription: error.localizedDescription, suggestedActions: ["重试"])
|
self.processingError = appError
|
||||||
self.currentWorkId = nil
|
self.currentWorkId = nil
|
||||||
self.currentProcessingTask = nil
|
self.currentProcessingTask = nil
|
||||||
}
|
}
|
||||||
Analytics.shared.logError(.buildLivePhotoFail, error: error)
|
Analytics.shared.logAppError(.buildLivePhotoFail, appError: appError)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import SwiftUI
|
|||||||
import PhotosUI
|
import PhotosUI
|
||||||
import AVKit
|
import AVKit
|
||||||
import Photos
|
import Photos
|
||||||
|
import LivePhotoCore
|
||||||
|
|
||||||
struct HomeView: View {
|
struct HomeView: View {
|
||||||
@Environment(AppState.self) private var appState
|
@Environment(AppState.self) private var appState
|
||||||
@@ -279,7 +280,12 @@ struct HomeView: View {
|
|||||||
errorMessage = String(format: format, error.localizedDescription)
|
errorMessage = String(format: format, error.localizedDescription)
|
||||||
isLoading = false
|
isLoading = false
|
||||||
selectedItem = nil
|
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 photoSize = livePhoto.size
|
||||||
let ratio = photoSize.width / max(photoSize.height, 1)
|
let ratio = photoSize.width / max(photoSize.height, 1)
|
||||||
SoftCard(padding: DesignTokens.Spacing.md) {
|
SoftCard(padding: DesignTokens.Spacing.md) {
|
||||||
LivePhotoPreviewView(livePhoto: livePhoto)
|
// PHLivePhotoView 无 intrinsic size,用 Color.clear 撑出正确比例
|
||||||
|
Color.clear
|
||||||
.aspectRatio(ratio, contentMode: .fit)
|
.aspectRatio(ratio, contentMode: .fit)
|
||||||
.frame(maxHeight: 360)
|
.frame(maxHeight: 360)
|
||||||
|
.overlay {
|
||||||
|
LivePhotoPreviewView(livePhoto: livePhoto)
|
||||||
|
}
|
||||||
.clipShape(RoundedRectangle(cornerRadius: DesignTokens.Radius.lg))
|
.clipShape(RoundedRectangle(cornerRadius: DesignTokens.Radius.lg))
|
||||||
.accessibilityLabel(String(localized: "result.livePhotoPreview.accessibilityLabel"))
|
.accessibilityLabel(String(localized: "result.livePhotoPreview.accessibilityLabel"))
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(String(localized: "result.livePhotoPreview.hint"))
|
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 cacheSize: String = String(localized: "common.calculating")
|
||||||
@State private var showingClearCacheAlert = false
|
@State private var showingClearCacheAlert = false
|
||||||
@State private var showingClearRecentWorksAlert = false
|
@State private var showingClearRecentWorksAlert = false
|
||||||
@State private var feedbackPackageURL: URL?
|
@State private var feedbackPackageURL: IdentifiableURL?
|
||||||
@State private var showingShareSheet = false
|
|
||||||
@State private var showingLanguageChangeAlert = false
|
@State private var showingLanguageChangeAlert = false
|
||||||
@State private var showingFeedbackConfirmAlert = false
|
@State private var showingFeedbackConfirmAlert = false
|
||||||
@State private var pendingLanguage: LanguageManager.Language?
|
@State private var pendingLanguage: LanguageManager.Language?
|
||||||
@@ -182,10 +181,8 @@ struct SettingsView: View {
|
|||||||
} message: {
|
} message: {
|
||||||
Text(String(localized: "settings.feedbackConfirmMessage"))
|
Text(String(localized: "settings.feedbackConfirmMessage"))
|
||||||
}
|
}
|
||||||
.sheet(isPresented: $showingShareSheet) {
|
.sheet(item: $feedbackPackageURL) { item in
|
||||||
if let url = feedbackPackageURL {
|
ShareSheet(activityItems: [item.url])
|
||||||
ShareSheet(activityItems: [url])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,8 +296,7 @@ struct SettingsView: View {
|
|||||||
let url = await createFeedbackPackage()
|
let url = await createFeedbackPackage()
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
if let url {
|
if let url {
|
||||||
feedbackPackageURL = url
|
feedbackPackageURL = IdentifiableURL(url: url)
|
||||||
showingShareSheet = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -425,6 +421,12 @@ extension PHAuthorizationStatus: @retroactive CustomStringConvertible {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Identifiable URL Wrapper
|
||||||
|
struct IdentifiableURL: Identifiable {
|
||||||
|
let id = UUID()
|
||||||
|
let url: URL
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Share Sheet
|
// MARK: - Share Sheet
|
||||||
struct ShareSheet: UIViewControllerRepresentable {
|
struct ShareSheet: UIViewControllerRepresentable {
|
||||||
let activityItems: [Any]
|
let activityItems: [Any]
|
||||||
|
|||||||
Reference in New Issue
Block a user