Commit 339fa4019a2eb0be8d917797da6e9b8a321bd8ba

Authored by 权海
1 parent dd1f741d

feat(ui):首页/好友页互动入口

5.01 KB | W: | H:

2.25 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin

4.69 KB | W: | H:

2.98 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
@@ -163,7 +163,7 @@ class TodayTabBody extends StatelessWidget { @@ -163,7 +163,7 @@ class TodayTabBody extends StatelessWidget {
163 if (controller.isFriend || showInteractionEntry) 163 if (controller.isFriend || showInteractionEntry)
164 const Positioned( 164 const Positioned(
165 right: 16, 165 right: 16,
166 - bottom: 92, 166 + bottom: 160,
167 child: FriendInteractionFloatingEntry(), 167 child: FriendInteractionFloatingEntry(),
168 ), 168 ),
169 ], 169 ],
@@ -15,7 +15,7 @@ class TodayHrvNumberCard extends StatelessWidget { @@ -15,7 +15,7 @@ class TodayHrvNumberCard extends StatelessWidget {
15 @override 15 @override
16 Widget build(BuildContext context) { 16 Widget build(BuildContext context) {
17 return Container( 17 return Container(
18 - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), 18 + padding: const EdgeInsets.symmetric(vertical: 16),
19 decoration: BoxDecoration( 19 decoration: BoxDecoration(
20 color: Colors.white, 20 color: Colors.white,
21 borderRadius: BorderRadius.circular(16), 21 borderRadius: BorderRadius.circular(16),
@@ -87,7 +87,7 @@ class _NumberItem extends StatelessWidget { @@ -87,7 +87,7 @@ class _NumberItem extends StatelessWidget {
87 @override 87 @override
88 Widget build(BuildContext context) { 88 Widget build(BuildContext context) {
89 return Padding( 89 return Padding(
90 - padding: const EdgeInsets.symmetric(horizontal: 12), 90 + padding: const EdgeInsets.only(left: 20, right: 2),
91 child: Column( 91 child: Column(
92 crossAxisAlignment: CrossAxisAlignment.start, 92 crossAxisAlignment: CrossAxisAlignment.start,
93 children: [ 93 children: [
@@ -105,11 +105,8 @@ class _NumberItem extends StatelessWidget { @@ -105,11 +105,8 @@ class _NumberItem extends StatelessWidget {
105 ), 105 ),
106 ), 106 ),
107 ), 107 ),
108 - if (interactionEnabled != null)  
109 - FriendInteractionButton(enabled: interactionEnabled!),  
110 ], 108 ],
111 ), 109 ),
112 - const SizedBox(height: 6),  
113 Row( 110 Row(
114 crossAxisAlignment: CrossAxisAlignment.end, 111 crossAxisAlignment: CrossAxisAlignment.end,
115 children: [ 112 children: [
@@ -124,7 +121,7 @@ class _NumberItem extends StatelessWidget { @@ -124,7 +121,7 @@ class _NumberItem extends StatelessWidget {
124 ), 121 ),
125 const SizedBox(width: 4), 122 const SizedBox(width: 4),
126 Padding( 123 Padding(
127 - padding: const EdgeInsets.only(bottom: 3), 124 + padding: const EdgeInsets.only(bottom: 0),
128 child: Text( 125 child: Text(
129 unit, 126 unit,
130 style: TextStyle( 127 style: TextStyle(
@@ -134,6 +131,18 @@ class _NumberItem extends StatelessWidget { @@ -134,6 +131,18 @@ class _NumberItem extends StatelessWidget {
134 ), 131 ),
135 ), 132 ),
136 ), 133 ),
  134 + if (interactionEnabled != null) ...[
  135 + const SizedBox(width: 8),
  136 + FriendInteractionButton(
  137 + enabled: interactionEnabled!,
  138 + padding: const EdgeInsets.only(
  139 + left: 8,
  140 + right: 20,
  141 + top: 8,
  142 + bottom: 0,
  143 + ),
  144 + ),
  145 + ],
137 ], 146 ],
138 ), 147 ),
139 ], 148 ],
@@ -458,7 +458,7 @@ class _TodaySummaryCard extends StatelessWidget { @@ -458,7 +458,7 @@ class _TodaySummaryCard extends StatelessWidget {
458 458
459 return Container( 459 return Container(
460 margin: const EdgeInsets.only(bottom: 8), 460 margin: const EdgeInsets.only(bottom: 8),
461 - padding: const EdgeInsets.fromLTRB(20, 18, 20, 15), 461 + padding: const EdgeInsets.fromLTRB(20, 10, 10, 15),
462 decoration: BoxDecoration( 462 decoration: BoxDecoration(
463 color: Colors.white, 463 color: Colors.white,
464 borderRadius: BorderRadius.circular(16), 464 borderRadius: BorderRadius.circular(16),
@@ -477,28 +477,20 @@ class _TodaySummaryCard extends StatelessWidget { @@ -477,28 +477,20 @@ class _TodaySummaryCard extends StatelessWidget {
477 fontWeight: FontWeight.w600, 477 fontWeight: FontWeight.w600,
478 ), 478 ),
479 ), 479 ),
480 - if (interactionEnabled != null) ...[  
481 - const SizedBox(width: 8),  
482 - FriendInteractionButton(enabled: interactionEnabled!),  
483 - ],  
484 - const Spacer(),  
485 - Text(  
486 - actionText,  
487 - style: TextStyle(  
488 - color: colors.textSecondary,  
489 - fontSize: 12,  
490 - fontWeight: FontWeight.w400,  
491 - ),  
492 - ), 480 + SizedBox(width: 4),
493 Image.asset( 481 Image.asset(
494 'assets/images/common/ic_more_gray.png', 482 'assets/images/common/ic_more_gray.png',
495 width: 16, 483 width: 16,
496 height: 16, 484 height: 16,
497 color: colors.textTertiary, 485 color: colors.textTertiary,
498 ), 486 ),
  487 + const Spacer(),
  488 + if (interactionEnabled != null) ...[
  489 + FriendInteractionButton(enabled: interactionEnabled!),
  490 + ],
499 ], 491 ],
500 ), 492 ),
501 - const SizedBox(height: 16), 493 + const SizedBox(height: 8),
502 Row( 494 Row(
503 crossAxisAlignment: CrossAxisAlignment.start, 495 crossAxisAlignment: CrossAxisAlignment.start,
504 children: [ 496 children: [
@@ -6,11 +6,18 @@ class FriendInteractionButton extends StatelessWidget { @@ -6,11 +6,18 @@ class FriendInteractionButton extends StatelessWidget {
6 const FriendInteractionButton({ 6 const FriendInteractionButton({
7 super.key, 7 super.key,
8 required this.enabled, 8 required this.enabled,
9 - this.size = 24, 9 + this.size = 24,
  10 + this.padding = const EdgeInsets.only(
  11 + left: 20,
  12 + right: 10,
  13 + top: 8,
  14 + bottom: 8,
  15 + ),
10 }); 16 });
11 17
12 final bool enabled; 18 final bool enabled;
13 final double size; 19 final double size;
  20 + final EdgeInsets padding;
14 21
15 @override 22 @override
16 Widget build(BuildContext context) => Opacity( 23 Widget build(BuildContext context) => Opacity(
@@ -18,18 +25,12 @@ class FriendInteractionButton extends StatelessWidget { @@ -18,18 +25,12 @@ class FriendInteractionButton extends StatelessWidget {
18 child: GestureDetector( 25 child: GestureDetector(
19 behavior: HitTestBehavior.opaque, 26 behavior: HitTestBehavior.opaque,
20 onTap: enabled ? _openInteraction : null, 27 onTap: enabled ? _openInteraction : null,
21 - child: SizedBox(  
22 - width: size,  
23 - height: size,  
24 - child: DecoratedBox(  
25 - decoration: const BoxDecoration(  
26 - color: Color(0xFF845EEE),  
27 - shape: BoxShape.circle,  
28 - ),  
29 - child: Padding(  
30 - padding: EdgeInsets.all(size / 8),  
31 - child: Image.asset('assets/images/interact/icon_stick.png'),  
32 - ), 28 + child: Padding(
  29 + padding: padding,
  30 + child: SizedBox(
  31 + width: size,
  32 + height: size,
  33 + child: Image.asset('assets/images/interact/icon_stick.png'),
33 ), 34 ),
34 ), 35 ),
35 ), 36 ),
@@ -2136,6 +2136,11 @@ double _integerDouble(num value) => value.toInt().toDouble(); @@ -2136,6 +2136,11 @@ double _integerDouble(num value) => value.toInt().toDouble();
2136 int _unixSecondsNow() => DateTime.now().millisecondsSinceEpoch ~/ 1000; 2136 int _unixSecondsNow() => DateTime.now().millisecondsSinceEpoch ~/ 1000;
2137 2137
2138 class HealthRawStressLocalStore { 2138 class HealthRawStressLocalStore {
  2139 + // Version 12 deliberately re-runs the date-key migration. Some shipped
  2140 + // databases were stamped with version 11 before this column was present.
  2141 + // SQLite consequently skips the old (< 9) migration for those databases.
  2142 + static const _databaseVersion = 12;
  2143 +
2139 HealthRawStressLocalStore({ 2144 HealthRawStressLocalStore({
2140 Directory? rootDirectory, 2145 Directory? rootDirectory,
2141 DatabaseFactory? databaseFactory, 2146 DatabaseFactory? databaseFactory,
@@ -2625,7 +2630,7 @@ class HealthRawStressLocalStore { @@ -2625,7 +2630,7 @@ class HealthRawStressLocalStore {
2625 final db = await factory.openDatabase( 2630 final db = await factory.openDatabase(
2626 path, 2631 path,
2627 options: OpenDatabaseOptions( 2632 options: OpenDatabaseOptions(
2628 - version: 11, 2633 + version: _databaseVersion,
2629 onCreate: (db, version) async { 2634 onCreate: (db, version) async {
2630 await _createTables(db); 2635 await _createTables(db);
2631 }, 2636 },
@@ -2661,9 +2666,17 @@ class HealthRawStressLocalStore { @@ -2661,9 +2666,17 @@ class HealthRawStressLocalStore {
2661 if (oldVersion < 11) { 2666 if (oldVersion < 11) {
2662 await _createIndexes(db); 2667 await _createIndexes(db);
2663 } 2668 }
  2669 + if (oldVersion < _databaseVersion) {
  2670 + await _repairDateKeySchema(db);
  2671 + }
2664 }, 2672 },
2665 ), 2673 ),
2666 ); 2674 );
  2675 + // Do not rely exclusively on user_version here. Historical releases may
  2676 + // have recorded the target version even though their schema migration did
  2677 + // not complete. This is idempotent, so it also protects a database whose
  2678 + // migration was interrupted before the app was terminated.
  2679 + await _repairDateKeySchema(db);
2667 _opened[userId] = db; 2680 _opened[userId] = db;
2668 return db; 2681 return db;
2669 } 2682 }
@@ -2842,6 +2855,10 @@ CREATE TABLE IF NOT EXISTS $sleepResultsTable ( @@ -2842,6 +2855,10 @@ CREATE TABLE IF NOT EXISTS $sleepResultsTable (
2842 } 2855 }
2843 } 2856 }
2844 2857
  2858 + Future<void> _repairDateKeySchema(DatabaseExecutor db) async {
  2859 + await _addDateKeyColumns(db);
  2860 + }
  2861 +
2845 Future<void> _addPushSendTimeColumns(DatabaseExecutor db) async { 2862 Future<void> _addPushSendTimeColumns(DatabaseExecutor db) async {
2846 for (final table in const [ 2863 for (final table in const [
2847 hrvResultsTable, 2864 hrvResultsTable,
@@ -10,6 +10,10 @@ import 'huawei_health_data_type.dart'; @@ -10,6 +10,10 @@ import 'huawei_health_data_type.dart';
10 import 'ohos_health_raw_data_sync_service.dart'; 10 import 'ohos_health_raw_data_sync_service.dart';
11 11
12 class OhosHealthRawDataSqliteStore implements OhosHealthRawDataLocalStore { 12 class OhosHealthRawDataSqliteStore implements OhosHealthRawDataLocalStore {
  13 + // Re-run the date-key repair for databases that were marked as v2 before
  14 + // their dynamic raw-data tables completed the v2 migration.
  15 + static const _databaseVersion = 3;
  16 +
13 OhosHealthRawDataSqliteStore({ 17 OhosHealthRawDataSqliteStore({
14 required int Function()? userIdProvider, 18 required int Function()? userIdProvider,
15 Directory? rootDirectory, 19 Directory? rootDirectory,
@@ -417,15 +421,22 @@ class OhosHealthRawDataSqliteStore implements OhosHealthRawDataLocalStore { @@ -417,15 +421,22 @@ class OhosHealthRawDataSqliteStore implements OhosHealthRawDataLocalStore {
417 final db = await factory.openDatabase( 421 final db = await factory.openDatabase(
418 path, 422 path,
419 options: OpenDatabaseOptions( 423 options: OpenDatabaseOptions(
420 - version: 2, 424 + version: _databaseVersion,
421 onCreate: (db, version) => _createTables(db), 425 onCreate: (db, version) => _createTables(db),
422 onUpgrade: (db, oldVersion, newVersion) async { 426 onUpgrade: (db, oldVersion, newVersion) async {
423 if (oldVersion < 2) { 427 if (oldVersion < 2) {
424 await _addDateKeyColumns(db); 428 await _addDateKeyColumns(db);
425 } 429 }
  430 + if (oldVersion < _databaseVersion) {
  431 + await _repairDateKeySchema(db);
  432 + }
426 }, 433 },
427 ), 434 ),
428 ); 435 );
  436 + // Dynamic raw-data tables can be created while a prior app version is
  437 + // running. Do not trust user_version alone: make their date-key schema
  438 + // valid before any read or write uses the cached database handle.
  439 + await _repairDateKeySchema(db);
429 _opened[userId] = db; 440 _opened[userId] = db;
430 return db; 441 return db;
431 } 442 }
@@ -703,6 +714,10 @@ CREATE TABLE IF NOT EXISTS $table ( @@ -703,6 +714,10 @@ CREATE TABLE IF NOT EXISTS $table (
703 } 714 }
704 } 715 }
705 716
  717 + Future<void> _repairDateKeySchema(DatabaseExecutor db) async {
  718 + await _addDateKeyColumns(db);
  719 + }
  720 +
706 Future<void> _backfillDateKey(DatabaseExecutor db, String table) async { 721 Future<void> _backfillDateKey(DatabaseExecutor db, String table) async {
707 final columns = await db.rawQuery('PRAGMA table_info($table)'); 722 final columns = await db.rawQuery('PRAGMA table_info($table)');
708 final columnNames = 723 final columnNames =
@@ -138,3 +138,5 @@ flutter: @@ -138,3 +138,5 @@ flutter:
138 - assets/images/user_onboarding/oh/ 138 - assets/images/user_onboarding/oh/
139 - assets/images/premium/ 139 - assets/images/premium/
140 - assets/images/premium/zh/ 140 - assets/images/premium/zh/
  141 + - assets/images/interact/
  142 + - assets/images/interact/animations/