Commit 8c7326afc7a83bad58d3d7e57231cada6daf725e

Authored by 权海
1 parent 2bf8d2c5

feat(ui):完善watch主题

@@ -3,9 +3,7 @@ import 'package:doublefeel_flutter/core/network/api/friend_api.dart'; @@ -3,9 +3,7 @@ import 'package:doublefeel_flutter/core/network/api/friend_api.dart';
3 import 'package:doublefeel_flutter/core/network/api/health_api.dart'; 3 import 'package:doublefeel_flutter/core/network/api/health_api.dart';
4 import 'package:doublefeel_flutter/core/network/api/pay_api.dart'; 4 import 'package:doublefeel_flutter/core/network/api/pay_api.dart';
5 import 'package:doublefeel_flutter/core/network/api/vip_api.dart'; 5 import 'package:doublefeel_flutter/core/network/api/vip_api.dart';
6 -import 'package:doublefeel_flutter/core/services/health_kit_upload_service.dart';  
7 import 'package:doublefeel_flutter/core/services/user_state_service.dart'; 6 import 'package:doublefeel_flutter/core/services/user_state_service.dart';
8 -import 'package:doublefeel_flutter/app/apple_health_upload/apple_health_upload_tool.dart';  
9 import 'package:doublefeel_flutter/data/models/friend/friend_models.dart'; 7 import 'package:doublefeel_flutter/data/models/friend/friend_models.dart';
10 import 'package:get/get.dart'; 8 import 'package:get/get.dart';
11 9
@@ -20,8 +18,6 @@ class FriendHomeBinding extends Bindings { @@ -20,8 +18,6 @@ class FriendHomeBinding extends Bindings {
20 Get.find<HealthApi>(), 18 Get.find<HealthApi>(),
21 Get.find<FriendApi>(), 19 Get.find<FriendApi>(),
22 Get.find<UserStateService>(), 20 Get.find<UserStateService>(),
23 - Get.find<HealthKitUploadService>(),  
24 - Get.find<AppleHealthUploadTool>(),  
25 friendInfo: args, 21 friendInfo: args,
26 ), 22 ),
27 tag: 'friend_${args.friendUserId}', // 动态 tag,支持多个好友同时在路由栈中 23 tag: 'friend_${args.friendUserId}', // 动态 tag,支持多个好友同时在路由栈中
@@ -12,6 +12,7 @@ import 'package:doublefeel_flutter/core/util/app_toast.dart'; @@ -12,6 +12,7 @@ import 'package:doublefeel_flutter/core/util/app_toast.dart';
12 import 'package:doublefeel_flutter/data/models/health/health_v2_models.dart'; 12 import 'package:doublefeel_flutter/data/models/health/health_v2_models.dart';
13 import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; 13 import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
14 import 'package:doublefeel_flutter/pigeon/platform_api.g.dart'; 14 import 'package:doublefeel_flutter/pigeon/platform_api.g.dart';
  15 +import 'package:doublefeel_flutter/pigeon/wear_engine_api.g.dart';
15 import 'package:get/get.dart'; 16 import 'package:get/get.dart';
16 17
17 import '../data/friends_repository.dart'; 18 import '../data/friends_repository.dart';
@@ -28,7 +29,7 @@ class FriendsController extends GetxController { @@ -28,7 +29,7 @@ class FriendsController extends GetxController {
28 _selfHealthRepository = selfHealthRepository ?? 29 _selfHealthRepository = selfHealthRepository ??
29 SelfHealthRepositoryImpl(Get.find<HealthApi>()), 30 SelfHealthRepositoryImpl(Get.find<HealthApi>()),
30 _updateWatchOtherUserInfo = updateWatchOtherUserInfo ?? 31 _updateWatchOtherUserInfo = updateWatchOtherUserInfo ??
31 - ((info) => PlatformHostApi().refreshWatchAppAndWidgets()); 32 + ((info) => WearEngineHostApi().sendWatchSyncPayload(''));
32 33
33 static const maxFriends = 10; 34 static const maxFriends = 10;
34 35
@@ -42,6 +42,10 @@ class SelectFriendLogic { @@ -42,6 +42,10 @@ class SelectFriendLogic {
42 if (index < 0 || index >= friends.length) return null; 42 if (index < 0 || index >= friends.length) return null;
43 43
44 final selectedFriend = friends[index]; 44 final selectedFriend = friends[index];
  45 + if (selectedFriend.isOnWatchFace) {
  46 + return null;
  47 + }
  48 +
45 final userId = selectedFriend.userId; 49 final userId = selectedFriend.userId;
46 if (userId == null) return null; 50 if (userId == null) return null;
47 51
@@ -95,7 +95,7 @@ class _SelectFriendViewState extends State<SelectFriendView> { @@ -95,7 +95,7 @@ class _SelectFriendViewState extends State<SelectFriendView> {
95 95
96 Future<void> _syncSelectedFriend() async { 96 Future<void> _syncSelectedFriend() async {
97 final selectedFriend = await _logic.syncSelectedFriendToWatchFace(); 97 final selectedFriend = await _logic.syncSelectedFriendToWatchFace();
98 - if (selectedFriend != null) Get.back(result: selectedFriend); 98 + Get.back(result: selectedFriend);
99 } 99 }
100 } 100 }
101 101
@@ -26,8 +26,6 @@ class HomeBinding extends Bindings { @@ -26,8 +26,6 @@ class HomeBinding extends Bindings {
26 Get.find<HealthApi>(), 26 Get.find<HealthApi>(),
27 Get.find<FriendApi>(), 27 Get.find<FriendApi>(),
28 Get.find<UserStateService>(), 28 Get.find<UserStateService>(),
29 - Get.find<HealthKitUploadService>(),  
30 - Get.find<AppleHealthUploadTool>(),  
31 ), 29 ),
32 fenix: true, 30 fenix: true,
33 ); 31 );
1 import 'dart:async'; 1 import 'dart:async';
2 import 'dart:math'; 2 import 'dart:math';
3 3
4 -import 'package:doublefeel_flutter/app/apple_health_upload/apple_health_upload_tool.dart';  
5 import 'package:doublefeel_flutter/app/modules/friends/controllers/friend_trend_controller.dart'; 4 import 'package:doublefeel_flutter/app/modules/friends/controllers/friend_trend_controller.dart';
6 import 'package:doublefeel_flutter/app/modules/home/controllers/home_controller.dart'; 5 import 'package:doublefeel_flutter/app/modules/home/controllers/home_controller.dart';
7 import 'package:doublefeel_flutter/app/modules/home/controllers/trend/trend_controller.dart'; 6 import 'package:doublefeel_flutter/app/modules/home/controllers/trend/trend_controller.dart';
@@ -14,7 +13,6 @@ import 'package:doublefeel_flutter/core/network/api/health_api.dart'; @@ -14,7 +13,6 @@ import 'package:doublefeel_flutter/core/network/api/health_api.dart';
14 import 'package:doublefeel_flutter/core/network/api/pay_api.dart'; 13 import 'package:doublefeel_flutter/core/network/api/pay_api.dart';
15 import 'package:doublefeel_flutter/core/network/api/vip_api.dart'; 14 import 'package:doublefeel_flutter/core/network/api/vip_api.dart';
16 import 'package:doublefeel_flutter/core/result/app_result.dart'; 15 import 'package:doublefeel_flutter/core/result/app_result.dart';
17 -import 'package:doublefeel_flutter/core/services/health_kit_upload_service.dart';  
18 import 'package:doublefeel_flutter/core/services/user_state_service.dart'; 16 import 'package:doublefeel_flutter/core/services/user_state_service.dart';
19 import 'package:doublefeel_flutter/core/util/app_toast.dart'; 17 import 'package:doublefeel_flutter/core/util/app_toast.dart';
20 import 'package:doublefeel_flutter/data/local/user_account_storage.dart'; 18 import 'package:doublefeel_flutter/data/local/user_account_storage.dart';
@@ -59,9 +57,7 @@ class TodayController extends GetMaterialController { @@ -59,9 +57,7 @@ class TodayController extends GetMaterialController {
59 this._vipApi, 57 this._vipApi,
60 this._healthApi, 58 this._healthApi,
61 this._friendApi, 59 this._friendApi,
62 - this._userStateService,  
63 - this._healthKitUploadService,  
64 - this._appleHealthUploadTool, { 60 + this._userStateService, {
65 FriendItem? friendInfo, // null = 自己,非 null = 好友 61 FriendItem? friendInfo, // null = 自己,非 null = 好友
66 }) : _initialFriendInfo = friendInfo; 62 }) : _initialFriendInfo = friendInfo;
67 63
@@ -70,8 +66,6 @@ class TodayController extends GetMaterialController { @@ -70,8 +66,6 @@ class TodayController extends GetMaterialController {
70 final HealthApi _healthApi; 66 final HealthApi _healthApi;
71 final FriendApi _friendApi; 67 final FriendApi _friendApi;
72 final UserStateService _userStateService; 68 final UserStateService _userStateService;
73 - final HealthKitUploadService _healthKitUploadService;  
74 - final AppleHealthUploadTool _appleHealthUploadTool;  
75 final HealthKitHostApi _hostApi = HealthKitHostApi(); 69 final HealthKitHostApi _hostApi = HealthKitHostApi();
76 70
77 /// 好友的信息;null 表示查看自己的数据,非 null 表示查看好友的数据。 71 /// 好友的信息;null 表示查看自己的数据,非 null 表示查看好友的数据。
@@ -265,7 +259,7 @@ class TodayController extends GetMaterialController { @@ -265,7 +259,7 @@ class TodayController extends GetMaterialController {
265 Future<void> _performDataUpload() async { 259 Future<void> _performDataUpload() async {
266 try { 260 try {
267 final result = 261 final result =
268 - await _appleHealthUploadTool.uploadAllNewDataFromHealthKit(); 262 + await _hostApi.performHealthUpload();
269 // AppLogger.i( 263 // AppLogger.i(
270 // 'Apple Health upload finished: ' 264 // 'Apple Health upload finished: '
271 // 'common=${result.commonUploadSuccess}(${result.commonCount}), ' 265 // 'common=${result.commonUploadSuccess}(${result.commonCount}), '
@@ -54,7 +54,7 @@ class MyTab extends GetView<MyController> { @@ -54,7 +54,7 @@ class MyTab extends GetView<MyController> {
54 : _UnlockPremiumCard(controller), 54 : _UnlockPremiumCard(controller),
55 const SizedBox(height: 12), 55 const SizedBox(height: 12),
56 _WatchThemeCard( 56 _WatchThemeCard(
57 - themes: controller.officialWatchThemes, 57 + themes: controller.watchThemeItems,
58 isLoading: controller.isLoadingWatchThemes.value, 58 isLoading: controller.isLoadingWatchThemes.value,
59 onTap: () => controller.goWatchThemePage(), 59 onTap: () => controller.goWatchThemePage(),
60 ), 60 ),
@@ -213,6 +213,7 @@ class CreateWatchThemeController extends GetxController { @@ -213,6 +213,7 @@ class CreateWatchThemeController extends GetxController {
213 ), 213 ),
214 barrierDismissible: true, 214 barrierDismissible: true,
215 ); 215 );
  216 + Get.back();
216 if (abandon == true) { 217 if (abandon == true) {
217 Get.back(); 218 Get.back();
218 } 219 }
@@ -259,7 +260,7 @@ class CreateWatchThemeController extends GetxController { @@ -259,7 +260,7 @@ class CreateWatchThemeController extends GetxController {
259 } 260 }
260 261
261 final createdTheme = await _loadCreatedTheme(); 262 final createdTheme = await _loadCreatedTheme();
262 - await Get.toNamed( 263 + await Get.offAndToNamed(
263 Routes.WATCH_THEME_CUSTOM_PREVIEW, 264 Routes.WATCH_THEME_CUSTOM_PREVIEW,
264 arguments: { 265 arguments: {
265 'theme': createdTheme ?? _buildThemeItem(uploadedImageUrls), 266 'theme': createdTheme ?? _buildThemeItem(uploadedImageUrls),
@@ -4,10 +4,13 @@ import 'dart:convert'; @@ -4,10 +4,13 @@ import 'dart:convert';
4 import 'package:doublefeel_flutter/core/network/api/theme_api.dart'; 4 import 'package:doublefeel_flutter/core/network/api/theme_api.dart';
5 import 'package:doublefeel_flutter/core/result/app_result.dart'; 5 import 'package:doublefeel_flutter/core/result/app_result.dart';
6 import 'package:doublefeel_flutter/core/util/app_toast.dart'; 6 import 'package:doublefeel_flutter/core/util/app_toast.dart';
  7 +import 'package:doublefeel_flutter/pigeon/platform_api.g.dart';
7 import 'package:doublefeel_flutter/pigeon/wear_engine_api.g.dart'; 8 import 'package:doublefeel_flutter/pigeon/wear_engine_api.g.dart';
8 import 'package:flutter/material.dart'; 9 import 'package:flutter/material.dart';
9 import 'package:get/get.dart'; 10 import 'package:get/get.dart';
10 11
  12 +import '../../friends/models/friend_health_data.dart';
  13 +import '../../friends/views/select_friend_view.dart';
11 import '../models/watch_theme_models.dart'; 14 import '../models/watch_theme_models.dart';
12 import '../widgets/watch_theme_dialogs.dart'; 15 import '../widgets/watch_theme_dialogs.dart';
13 import '../widgets/watch_theme_no_watch_dialog.dart'; 16 import '../widgets/watch_theme_no_watch_dialog.dart';
@@ -108,8 +111,25 @@ class CustomWatchThemePreviewController extends GetxController { @@ -108,8 +111,25 @@ class CustomWatchThemePreviewController extends GetxController {
108 } 111 }
109 } 112 }
110 113
111 - void changeFriend() {  
112 - //TODO: - bottomSheet 的方式展示出 SelectFriendView 114 + Future<void> changeFriend() async {
  115 + final selectedFriend = await Get.bottomSheet<FriendHealthData>(
  116 + SizedBox(
  117 + height: Get.height * 0.9,
  118 + child: const SelectFriendView(),
  119 + ),
  120 + ignoreSafeArea: false,
  121 + isScrollControlled: true,
  122 + backgroundColor: Colors.transparent,
  123 + barrierColor: const Color(0xB3000000),
  124 + );
  125 + if (selectedFriend == null) return;
  126 +
  127 + await loadFriendTheme();
  128 + try {
  129 + await WearEngineHostApi().sendWatchSyncPayload('');
  130 + } catch (_) {
  131 + // The selected friend is saved on the server; native refresh can retry.
  132 + }
113 } 133 }
114 134
115 Future<void> addWatchFace() async { 135 Future<void> addWatchFace() async {
@@ -120,20 +140,20 @@ class CustomWatchThemePreviewController extends GetxController { @@ -120,20 +140,20 @@ class CustomWatchThemePreviewController extends GetxController {
120 device = null; 140 device = null;
121 } 141 }
122 if (device == null) { 142 if (device == null) {
123 - await Get.dialog<void>( 143 + await Get.bottomSheet<void>(
124 const WatchThemeNoWatchDialog(), 144 const WatchThemeNoWatchDialog(),
125 - barrierDismissible: true, 145 + backgroundColor: Colors.transparent,
126 barrierColor: const Color(0xB3000000), 146 barrierColor: const Color(0xB3000000),
127 ); 147 );
128 return; 148 return;
129 } 149 }
130 150
131 - await Get.dialog<void>( 151 + await Get.bottomSheet<void>(
132 WatchThemeSyncDialog( 152 WatchThemeSyncDialog(
133 themeImageUrl: themeItem.energeticImage, 153 themeImageUrl: themeItem.energeticImage,
134 onSync: applyAndSyncWatchFace, 154 onSync: applyAndSyncWatchFace,
135 ), 155 ),
136 - barrierDismissible: false, 156 + backgroundColor: Colors.transparent,
137 barrierColor: const Color(0xB3000000), 157 barrierColor: const Color(0xB3000000),
138 ); 158 );
139 } 159 }
@@ -4,10 +4,13 @@ import 'dart:convert'; @@ -4,10 +4,13 @@ import 'dart:convert';
4 import 'package:doublefeel_flutter/core/network/api/theme_api.dart'; 4 import 'package:doublefeel_flutter/core/network/api/theme_api.dart';
5 import 'package:doublefeel_flutter/core/result/app_result.dart'; 5 import 'package:doublefeel_flutter/core/result/app_result.dart';
6 import 'package:doublefeel_flutter/core/util/app_toast.dart'; 6 import 'package:doublefeel_flutter/core/util/app_toast.dart';
  7 +import 'package:doublefeel_flutter/pigeon/platform_api.g.dart';
7 import 'package:doublefeel_flutter/pigeon/wear_engine_api.g.dart'; 8 import 'package:doublefeel_flutter/pigeon/wear_engine_api.g.dart';
8 import 'package:flutter/material.dart'; 9 import 'package:flutter/material.dart';
9 import 'package:get/get.dart'; 10 import 'package:get/get.dart';
10 11
  12 +import '../../friends/models/friend_health_data.dart';
  13 +import '../../friends/views/select_friend_view.dart';
11 import '../models/watch_theme_models.dart'; 14 import '../models/watch_theme_models.dart';
12 import '../widgets/watch_theme_no_watch_dialog.dart'; 15 import '../widgets/watch_theme_no_watch_dialog.dart';
13 import '../widgets/watch_theme_sync_dialog.dart'; 16 import '../widgets/watch_theme_sync_dialog.dart';
@@ -86,26 +89,43 @@ class WatchThemePreviewController extends GetxController { @@ -86,26 +89,43 @@ class WatchThemePreviewController extends GetxController {
86 device = null; 89 device = null;
87 } 90 }
88 if (device == null) { 91 if (device == null) {
89 - await Get.dialog<void>( 92 + await Get.bottomSheet<void>(
90 const WatchThemeNoWatchDialog(), 93 const WatchThemeNoWatchDialog(),
91 - barrierDismissible: true, 94 + backgroundColor: Colors.transparent,
92 barrierColor: const Color(0xB3000000), 95 barrierColor: const Color(0xB3000000),
93 ); 96 );
94 return; 97 return;
95 } 98 }
96 99
97 - await Get.dialog<void>( 100 + await Get.bottomSheet<void>(
98 WatchThemeSyncDialog( 101 WatchThemeSyncDialog(
99 themeImageUrl: themeItem.energeticImage, 102 themeImageUrl: themeItem.energeticImage,
100 onSync: applyAndSyncWatchFace, 103 onSync: applyAndSyncWatchFace,
101 ), 104 ),
102 - barrierDismissible: false, 105 + backgroundColor: Colors.transparent,
103 barrierColor: const Color(0xB3000000), 106 barrierColor: const Color(0xB3000000),
104 ); 107 );
105 } 108 }
106 109
107 - void changeFriend() {  
108 - //TODO: - bottomSheet 的方式展示出 SelectFriendView 110 + Future<void> changeFriend() async {
  111 + final selectedFriend = await Get.bottomSheet<FriendHealthData>(
  112 + SizedBox(
  113 + height: Get.height * 0.9,
  114 + child: const SelectFriendView(),
  115 + ),
  116 + ignoreSafeArea: false,
  117 + isScrollControlled: true,
  118 + backgroundColor: Colors.transparent,
  119 + barrierColor: const Color(0xB3000000),
  120 + );
  121 + if (selectedFriend == null) return;
  122 +
  123 + await loadFriendTheme();
  124 + try {
  125 + await WearEngineHostApi().sendWatchSyncPayload('');
  126 + } catch (_) {
  127 + // The selected friend is saved on the server; native refresh can retry.
  128 + }
109 } 129 }
110 130
111 Future<bool> applyAndSyncWatchFace() async { 131 Future<bool> applyAndSyncWatchFace() async {
@@ -124,7 +124,7 @@ class _EditorCard extends StatelessWidget { @@ -124,7 +124,7 @@ class _EditorCard extends StatelessWidget {
124 ), 124 ),
125 SizedBox(height: 4), 125 SizedBox(height: 4),
126 Text( 126 Text(
127 - '支持上传图片、视频、Live图、Gif、最长5秒', 127 + '仅支持上传图片',
128 style: TextStyle( 128 style: TextStyle(
129 color: WatchThemeColors.textSecondary, 129 color: WatchThemeColors.textSecondary,
130 fontSize: 12, 130 fontSize: 12,
@@ -63,9 +63,9 @@ class CustomWatchThemePreviewView @@ -63,9 +63,9 @@ class CustomWatchThemePreviewView
63 style: TextStyle( 63 style: TextStyle(
64 color: const Color(0xFFFC4447), 64 color: const Color(0xFFFC4447),
65 fontSize: 14, 65 fontSize: 14,
66 - fontWeight: FontWeight.w500, 66 + fontWeight: FontWeight.w600,
67 ), 67 ),
68 - ), 68 + ).paddingOnly(left: 4, right: 4, top: 4, bottom: 4),
69 ), 69 ),
70 ), 70 ),
71 Expanded( 71 Expanded(
@@ -88,6 +88,7 @@ class CustomWatchThemePreviewView @@ -88,6 +88,7 @@ class CustomWatchThemePreviewView
88 controller.themeItem.energeticImage, 88 controller.themeItem.energeticImage,
89 themeImageUrl2: 89 themeImageUrl2:
90 controller.friendThemeItem.value?.normalImage, 90 controller.friendThemeItem.value?.normalImage,
  91 + switchFriend: controller.changeFriend,
91 ); 92 );
92 }), 93 }),
93 ], 94 ],
@@ -73,6 +73,7 @@ class WatchThemePreviewView extends GetView<WatchThemePreviewController> { @@ -73,6 +73,7 @@ class WatchThemePreviewView extends GetView<WatchThemePreviewController> {
73 controller.themeItem.energeticImage, 73 controller.themeItem.energeticImage,
74 themeImageUrl2: controller 74 themeImageUrl2: controller
75 .friendThemeItem.value?.normalImage, 75 .friendThemeItem.value?.normalImage,
  76 + switchFriend: controller.changeFriend,
76 ); 77 );
77 }, 78 },
78 ), 79 ),
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
  2 +import 'package:get/utils.dart';
2 3
3 import '../models/watch_theme_models.dart'; 4 import '../models/watch_theme_models.dart';
4 import 'watch_theme_character_avatar.dart'; 5 import 'watch_theme_character_avatar.dart';
@@ -47,24 +48,30 @@ class CustomThemeCard extends StatelessWidget { @@ -47,24 +48,30 @@ class CustomThemeCard extends StatelessWidget {
47 ), 48 ),
48 SizedBox(height: 14), 49 SizedBox(height: 14),
49 _CreateThemeButton(onTap: onCreateTap), 50 _CreateThemeButton(onTap: onCreateTap),
50 - if (customThemes.isEmpty) ...[  
51 - SizedBox(height: 12),  
52 - Row(  
53 - children: [  
54 - for (var index = 0; index < customThemes.length; index++) ...[  
55 - _CustomThemeItem( 51 + customThemes.isEmpty
  52 + ? SizedBox(height: 0)
  53 + : SizedBox(
  54 + height: 112,
  55 + child: ListView.separated(
  56 + scrollDirection: Axis.horizontal,
  57 + padding: EdgeInsets.zero,
  58 + itemBuilder: (context, index) {
  59 + return _CustomThemeItem(
56 item: customThemes[index], 60 item: customThemes[index],
57 selected: customThemes[index].id != null && 61 selected: customThemes[index].id != null &&
58 customThemes[index].id == activeThemeId, 62 customThemes[index].id == activeThemeId,
59 onTap: onThemeTap == null 63 onTap: onThemeTap == null
60 ? null 64 ? null
61 : () => onThemeTap!(customThemes[index]), 65 : () => onThemeTap!(customThemes[index]),
62 - ),  
63 - if (index != customThemes.length - 1) SizedBox(width: 20),  
64 - ],  
65 - ],  
66 - ),  
67 - ], 66 + );
  67 + },
  68 + separatorBuilder: (context, index) {
  69 + return SizedBox(
  70 + width: 20,
  71 + );
  72 + },
  73 + itemCount: customThemes.length),
  74 + ).paddingOnly(top: 12),
68 ], 75 ],
69 ), 76 ),
70 ); 77 );
@@ -9,11 +9,13 @@ class DialPreviewCard extends StatelessWidget { @@ -9,11 +9,13 @@ class DialPreviewCard extends StatelessWidget {
9 bool showFriend; 9 bool showFriend;
10 final String? themeImageUrl; 10 final String? themeImageUrl;
11 final String? themeImageUrl2; 11 final String? themeImageUrl2;
  12 + final Function()? switchFriend;
12 DialPreviewCard( 13 DialPreviewCard(
13 {super.key, 14 {super.key,
14 required this.showFriend, 15 required this.showFriend,
15 this.themeImageUrl, 16 this.themeImageUrl,
16 - this.themeImageUrl2}); 17 + this.themeImageUrl2,
  18 + this.switchFriend});
17 19
18 @override 20 @override
19 Widget build(BuildContext context) { 21 Widget build(BuildContext context) {
@@ -41,6 +43,7 @@ class DialPreviewCard extends StatelessWidget { @@ -41,6 +43,7 @@ class DialPreviewCard extends StatelessWidget {
41 type: WatchFacePreviewType.coupleSmall, 43 type: WatchFacePreviewType.coupleSmall,
42 themeImageUrl: themeImageUrl, 44 themeImageUrl: themeImageUrl,
43 themeImageUrl2: themeImageUrl2, 45 themeImageUrl2: themeImageUrl2,
  46 + switchFriend: switchFriend,
44 ); 47 );
45 } 48 }
46 return WatchFacePreview( 49 return WatchFacePreview(