-
Notifications
You must be signed in to change notification settings - Fork 543
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WAL Sync UI #993
WAL Sync UI #993
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -252,7 +252,7 @@ Future<List<ServerMemory>> sendStorageToBackend(File file, String sdCardDateTime | |
} | ||
} | ||
|
||
Future<bool> syncLocalFiles(List<File> files) async { | ||
Future<(Map<String, dynamic>?, bool)> syncLocalFiles(List<File> files) async { | ||
var request = http.MultipartRequest( | ||
'POST', | ||
Uri.parse('${Env.apiBaseUrl}v1/sync-local-files'), | ||
|
@@ -268,7 +268,7 @@ Future<bool> syncLocalFiles(List<File> files) async { | |
|
||
if (response.statusCode == 200) { | ||
debugPrint('syncLocalFile Response body: ${jsonDecode(response.body)}'); | ||
return true; | ||
return (jsonDecode(response.body) as Map<String, dynamic>, true); | ||
} else { | ||
debugPrint('Failed to upload sample. Status code: ${response.statusCode}'); | ||
throw Exception('Failed to upload sample. Status code: ${response.statusCode}'); | ||
Comment on lines
+271
to
274
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The return value of the - return true;
+ return (jsonDecode(response.body) as Map<String, dynamic>, true); |
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,47 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:friend_private/backend/schema/memory.dart'; | ||
import 'package:friend_private/pages/capture/widgets/widgets.dart'; | ||
import 'package:friend_private/pages/memories/sync_page.dart'; | ||
import 'package:friend_private/pages/memories/widgets/date_list_item.dart'; | ||
import 'package:friend_private/pages/memories/widgets/processing_capture.dart'; | ||
import 'package:friend_private/providers/memory_provider.dart'; | ||
import 'package:friend_private/utils/other/temp.dart'; | ||
import 'package:provider/provider.dart'; | ||
import 'package:visibility_detector/visibility_detector.dart'; | ||
|
||
import 'widgets/empty_memories.dart'; | ||
import 'widgets/memory_list_item.dart'; | ||
|
||
String secondsToHumanReadable(int seconds) { | ||
if (seconds < 60) { | ||
return '$seconds secs'; | ||
} else if (seconds < 3600) { | ||
var minutes = (seconds / 60).floor(); | ||
var remainingSeconds = seconds % 60; | ||
if (remainingSeconds == 0) { | ||
return '$minutes mins'; | ||
} else { | ||
return '$minutes mins $remainingSeconds secs'; | ||
} | ||
} else if (seconds < 86400) { | ||
var hours = (seconds / 3600).floor(); | ||
var remainingMinutes = (seconds % 3600 / 60).floor(); | ||
if (remainingMinutes == 0) { | ||
return '$hours hours'; | ||
} else { | ||
return '$hours hours $remainingMinutes mins'; | ||
} | ||
} else { | ||
var days = (seconds / 86400).floor(); | ||
var remainingHours = (seconds % 86400 / 3600).floor(); | ||
if (remainingHours == 0) { | ||
return '$days days'; | ||
} else { | ||
return '$days days $remainingHours hours'; | ||
} | ||
} | ||
} | ||
Comment on lines
+15
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The - String secondsToHumanReadable(int seconds) {
- if (seconds < 60) {
- return '$seconds secs';
- } else if (seconds < 3600) {
- var minutes = (seconds / 60).floor();
- var remainingSeconds = seconds % 60;
- if (remainingSeconds == 0) {
- return '$minutes mins';
- } else {
- return '$minutes mins $remainingSeconds secs';
- }
- } else if (seconds < 86400) {
- var hours = (seconds / 3600).floor();
- var remainingMinutes = (seconds % 3600 / 60).floor();
- if (remainingMinutes == 0) {
- return '$hours hours';
- } else {
- return '$hours hours $remainingMinutes mins';
- }
- } else {
- var days = (seconds / 86400).floor();
- var remainingHours = (seconds % 86400 / 3600).floor();
- if (remainingHours == 0) {
- return '$days days';
- } else {
- return '$days days $remainingHours hours';
- }
- }
- } |
||
|
||
class MemoriesPage extends StatefulWidget { | ||
const MemoriesPage({super.key}); | ||
|
||
|
@@ -46,25 +78,32 @@ class _MemoriesPageState extends State<MemoriesPage> with AutomaticKeepAliveClie | |
}, | ||
child: CustomScrollView( | ||
slivers: [ | ||
// TODO: FIXME | ||
SliverToBoxAdapter( | ||
child: memoryProvider.missingWals.isNotEmpty | ||
? Padding( | ||
padding: const EdgeInsets.all(32.0), | ||
child: Center( | ||
child: GestureDetector( | ||
onTap: () { | ||
memoryProvider.syncWals(); | ||
}, | ||
child: memoryProvider.walsSyncedProgress == 0.0 | ||
? Text( | ||
"You have ${memoryProvider.missingWals.map((val) => val.seconds).reduce((a, b) => a + b)}s stereo localy, sync now?") | ||
: Text("${(memoryProvider.walsSyncedProgress * 100).toInt()}%"), | ||
child: memoryProvider.missingWals.isNotEmpty | ||
? GestureDetector( | ||
onTap: () { | ||
routeToPage(context, const SyncPage()); | ||
}, | ||
child: Container( | ||
width: double.maxFinite, | ||
decoration: BoxDecoration( | ||
color: Colors.grey.shade900, | ||
borderRadius: const BorderRadius.all(Radius.circular(12)), | ||
), | ||
margin: const EdgeInsets.fromLTRB(16, 18, 16, 0), | ||
padding: const EdgeInsets.all(16), | ||
child: ListTile( | ||
leading: const Icon(Icons.record_voice_over_rounded), | ||
title: Text( | ||
'You have ${secondsToHumanReadable(memoryProvider.missingWals.map((val) => val.seconds).reduce((a, b) => a + b))} of conversation locally, sync now?', | ||
style: const TextStyle(color: Colors.white, fontSize: 16), | ||
), | ||
), | ||
) | ||
: SizedBox.shrink()), | ||
const SliverToBoxAdapter(child: SizedBox(height: 32)), | ||
), | ||
) | ||
: const SizedBox.shrink(), | ||
), | ||
const SliverToBoxAdapter(child: SizedBox(height: 26)), | ||
const SliverToBoxAdapter(child: SpeechProfileCardWidget()), | ||
const SliverToBoxAdapter(child: UpdateFirmwareCardWidget()), | ||
const SliverToBoxAdapter(child: MemoryCaptureWidget()), | ||
|
@@ -95,6 +134,7 @@ class _MemoriesPageState extends State<MemoriesPage> with AutomaticKeepAliveClie | |
childCount: memoryProvider.groupedMemories.length + 1, | ||
(context, index) { | ||
if (index == memoryProvider.groupedMemories.length) { | ||
print('loading more memories'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid using - print('loading more memories');
+ // Use a logging package for logging
+ log.info('loading more memories'); |
||
if (memoryProvider.isLoadingMemories) { | ||
return const Center( | ||
child: Padding( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:friend_private/pages/memories/widgets/sync_animation.dart'; | ||
import 'package:friend_private/providers/memory_provider.dart'; | ||
import 'package:friend_private/utils/other/temp.dart'; | ||
import 'package:gradient_borders/box_borders/gradient_box_border.dart'; | ||
import 'package:provider/provider.dart'; | ||
|
||
import 'synced_memories_page.dart'; | ||
|
||
class SyncPage extends StatefulWidget { | ||
const SyncPage({super.key}); | ||
|
||
@override | ||
State<SyncPage> createState() => _SyncPageState(); | ||
} | ||
|
||
class _SyncPageState extends State<SyncPage> { | ||
bool _isAnimating = false; | ||
|
||
void _toggleAnimation() { | ||
setState(() { | ||
_isAnimating = !_isAnimating; | ||
}); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return PopScope( | ||
onPopInvoked: (didPop) { | ||
Provider.of<MemoryProvider>(context, listen: false).clearSyncResult(); | ||
}, | ||
Comment on lines
+29
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
child: Scaffold( | ||
appBar: AppBar( | ||
title: const Text('Sync Memories'), | ||
backgroundColor: Theme.of(context).colorScheme.primary, | ||
), | ||
backgroundColor: Theme.of(context).colorScheme.primary, | ||
body: Consumer<MemoryProvider>( | ||
builder: (context, memoryProvider, child) { | ||
return Center( | ||
child: Column( | ||
children: [ | ||
const SizedBox(height: 80), | ||
child!, | ||
const SizedBox(height: 80), | ||
memoryProvider.isSyncing || memoryProvider.syncCompleted | ||
? const SizedBox() | ||
: Container( | ||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 0), | ||
decoration: BoxDecoration( | ||
border: const GradientBoxBorder( | ||
gradient: LinearGradient(colors: [ | ||
Color.fromARGB(127, 208, 208, 208), | ||
Color.fromARGB(127, 188, 99, 121), | ||
Color.fromARGB(127, 86, 101, 182), | ||
Color.fromARGB(127, 126, 190, 236) | ||
]), | ||
width: 2, | ||
), | ||
borderRadius: BorderRadius.circular(12), | ||
), | ||
child: TextButton( | ||
onPressed: () async { | ||
_toggleAnimation(); | ||
await memoryProvider.syncWals(); | ||
_toggleAnimation(); | ||
}, | ||
Comment on lines
+64
to
+67
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The - _toggleAnimation();
- await memoryProvider.syncWals();
- _toggleAnimation();
+ _toggleAnimation();
+ try {
+ await memoryProvider.syncWals();
+ } finally {
+ _toggleAnimation();
+ } |
||
child: const Text( | ||
'Sync Now', | ||
style: TextStyle(color: Colors.white, fontSize: 16), | ||
), | ||
), | ||
), | ||
const SizedBox( | ||
height: 10, | ||
), | ||
memoryProvider.isSyncing | ||
? Text( | ||
'${memoryProvider.walsSyncedProgress}% synced', | ||
style: const TextStyle(color: Colors.white, fontSize: 16), | ||
) | ||
: const SizedBox.shrink(), | ||
const SizedBox( | ||
height: 10, | ||
), | ||
memoryProvider.syncCompleted && memoryProvider.syncResult != null | ||
? Column( | ||
children: [ | ||
const Text( | ||
'Memories Synced Successfully 🎉', | ||
style: TextStyle(color: Colors.white, fontSize: 16), | ||
), | ||
const SizedBox( | ||
height: 18, | ||
), | ||
(memoryProvider.syncResult!['new_memories'].isNotEmpty || | ||
memoryProvider.syncResult!['updated_memories'].isNotEmpty) | ||
? Container( | ||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 0), | ||
decoration: BoxDecoration( | ||
border: const GradientBoxBorder( | ||
gradient: LinearGradient(colors: [ | ||
Color.fromARGB(127, 208, 208, 208), | ||
Color.fromARGB(127, 188, 99, 121), | ||
Color.fromARGB(127, 86, 101, 182), | ||
Color.fromARGB(127, 126, 190, 236) | ||
]), | ||
width: 2, | ||
), | ||
borderRadius: BorderRadius.circular(12), | ||
), | ||
child: TextButton( | ||
onPressed: () { | ||
routeToPage(context, const SyncedMemoriesPage()); | ||
}, | ||
child: const Text( | ||
'View Synced Memories', | ||
style: TextStyle(color: Colors.white, fontSize: 16), | ||
), | ||
), | ||
) | ||
: const SizedBox.shrink(), | ||
Comment on lines
+96
to
+122
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's no null safety check for - (memoryProvider.syncResult!['new_memories'].isNotEmpty ||
- memoryProvider.syncResult!['updated_memories'].isNotEmpty)
+ (memoryProvider.syncResult!['new_memories']?.isNotEmpty ?? false ||
+ memoryProvider.syncResult!['updated_memories']?.isNotEmpty ?? false) |
||
], | ||
) | ||
: const SizedBox.shrink(), | ||
], | ||
), | ||
); | ||
}, | ||
child: RepaintBoundary( | ||
child: SyncAnimation( | ||
isAnimating: _isAnimating, | ||
onStart: () {}, | ||
onStop: () {}, | ||
dotsPerRing: 12, | ||
), | ||
), | ||
), | ||
), | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:friend_private/providers/memory_provider.dart'; | ||
import 'package:provider/provider.dart'; | ||
|
||
class SyncedMemoriesPage extends StatelessWidget { | ||
final Map<String, dynamic>? res; | ||
const SyncedMemoriesPage({super.key, this.res}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Scaffold( | ||
appBar: AppBar( | ||
title: const Text('Synced Memories'), | ||
backgroundColor: Theme.of(context).colorScheme.primary, | ||
), | ||
backgroundColor: Theme.of(context).colorScheme.primary, | ||
body: Consumer<MemoryProvider>( | ||
builder: (context, memoryProvider, child) { | ||
return Column( | ||
mainAxisSize: MainAxisSize.min, | ||
children: [ | ||
const Text( | ||
"Updated Memories", | ||
style: TextStyle(color: Colors.white), | ||
), | ||
ListView.separated( | ||
shrinkWrap: true, | ||
itemBuilder: (ctx, i) { | ||
return Container(); | ||
}, | ||
separatorBuilder: (ctx, i) { | ||
return const SizedBox( | ||
height: 10, | ||
); | ||
}, | ||
itemCount: memoryProvider.syncResult!['updated_memories'].length, | ||
), | ||
const Text( | ||
"New Memories", | ||
style: TextStyle(color: Colors.white), | ||
), | ||
ListView.separated( | ||
shrinkWrap: true, | ||
itemBuilder: (ctx, i) { | ||
return Container(); | ||
}, | ||
separatorBuilder: (ctx, i) { | ||
return const SizedBox( | ||
height: 10, | ||
); | ||
}, | ||
itemCount: memoryProvider.syncResult!['new_memories'].length, | ||
), | ||
], | ||
); | ||
}, | ||
), | ||
); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Entelligence.AI
The return type of
syncLocalFiles
has been changed fromFuture<bool>
toFuture<(Map<String, dynamic>?, bool)>
. This change is significant as it affects the external interface of this function. Any code that calls this function will need to be updated to handle the new return type. Ensure that all call sites have been updated accordingly.