Skip to content
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

Fix and improve facts UX in app #1823

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions app/lib/backend/http/api/facts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import 'package:friend_private/backend/http/shared.dart';
import 'package:friend_private/backend/schema/fact.dart';
import 'package:friend_private/env/env.dart';

Future<bool> createFact(String content, FactCategory category) async {
Future<bool> createFactServer(String content, FactCategory category) async {
var response = await makeApiCall(
url: '${Env.apiBaseUrl}v1/facts',
headers: {},
Expand Down Expand Up @@ -33,7 +33,7 @@ Future<List<Fact>> getFacts({int limit = 100, int offset = 0}) async {
return facts.map((fact) => Fact.fromJson(fact)).toList();
}

Future<bool> deleteFact(String factId) async {
Future<bool> deleteFactServer(String factId) async {
var response = await makeApiCall(
url: '${Env.apiBaseUrl}v1/facts/$factId',
headers: {},
Expand All @@ -45,7 +45,7 @@ Future<bool> deleteFact(String factId) async {
return response.statusCode == 200;
}

Future<bool> reviewFact(String factId, bool value) async {
Future<bool> reviewFactServer(String factId, bool value) async {
var response = await makeApiCall(
url: '${Env.apiBaseUrl}v1/facts/$factId/review?value=$value',
headers: {},
Expand All @@ -57,7 +57,7 @@ Future<bool> reviewFact(String factId, bool value) async {
return response.statusCode == 200;
}

Future<bool> editFact(String factId, String value) async {
Future<bool> editFactServer(String factId, String value) async {
var response = await makeApiCall(
url: '${Env.apiBaseUrl}v1/facts/$factId?value=$value',
headers: {},
Expand Down
15 changes: 9 additions & 6 deletions app/lib/backend/schema/fact.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,19 @@ class Fact {
id: json['id'],
uid: json['uid'],
content: json['content'],
category: FactCategory.values.firstWhere((e) => e.toString() == 'FactCategory.${json['category']}'),
category: FactCategory.values.firstWhere(
(e) => e.toString().split('.').last == json['category'],
orElse: () => FactCategory.other,
),
createdAt: DateTime.parse(json['created_at']).toLocal(),
updatedAt: DateTime.parse(json['updated_at']).toLocal(),
conversationId: json['memory_id'],
conversationCategory: json['memory_category'],
reviewed: json['reviewed'],
reviewed: json['reviewed'] ?? false,
userReview: json['user_review'],
manuallyAdded: json['manually_added'],
edited: json['edited'],
deleted: json['deleted'],
manuallyAdded: json['manually_added'] ?? false,
edited: json['edited'] ?? false,
deleted: json['deleted'] ?? false,
);
}

Expand All @@ -58,7 +61,7 @@ class Fact {
'created_at': createdAt.toUtc().toIso8601String(),
'updated_at': updatedAt.toUtc().toIso8601String(),
'memory_id': conversationId,
'memory_category': conversationCategory.toString().split('.').last,
'memory_category': conversationCategory?.toString().split('.').last,
'reviewed': reviewed,
'user_review': userReview,
'manually_added': manuallyAdded,
Expand Down
2 changes: 2 additions & 0 deletions app/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import 'package:friend_private/providers/capture_provider.dart';
import 'package:friend_private/providers/connectivity_provider.dart';
import 'package:friend_private/providers/developer_mode_provider.dart';
import 'package:friend_private/providers/device_provider.dart';
import 'package:friend_private/providers/facts_provider.dart';
import 'package:friend_private/providers/home_provider.dart';
import 'package:friend_private/providers/conversation_provider.dart';
import 'package:friend_private/providers/message_provider.dart';
Expand Down Expand Up @@ -213,6 +214,7 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
),
ChangeNotifierProvider(create: (context) => PaymentMethodProvider()),
ChangeNotifierProvider(create: (context) => PersonaProvider()),
ChangeNotifierProvider(create: (context) => FactsProvider()),
],
builder: (context, child) {
return WithForegroundTask(
Expand Down
102 changes: 102 additions & 0 deletions app/lib/pages/facts/category_facts_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import 'package:flutter/material.dart';
import 'package:friend_private/backend/schema/fact.dart';
import 'package:friend_private/providers/facts_provider.dart';
import 'package:friend_private/utils/analytics/mixpanel.dart';
import 'package:provider/provider.dart';

import 'widgets/fact_edit_sheet.dart';
import 'widgets/fact_item.dart';
import 'widgets/fact_dialog.dart';

class CategoryFactsPage extends StatelessWidget {
final FactCategory category;

const CategoryFactsPage({
super.key,
required this.category,
});

@override
Widget build(BuildContext context) {
return Consumer<FactsProvider>(builder: (context, provider, child) {
return Scaffold(
backgroundColor: Theme.of(context).colorScheme.primary,
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.primary,
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
category.toString().split('.').last[0].toUpperCase() + category.toString().split('.').last.substring(1),
),
Text(
'${provider.filteredFacts.length} facts',
style: TextStyle(
fontSize: 14,
color: Colors.grey.shade400,
fontWeight: FontWeight.normal,
),
),
],
),
actions: [
IconButton(
icon: const Icon(Icons.add),
onPressed: () {
showFactDialog(context, provider);
MixpanelManager().factsPageCreateFactBtn();
},
),
],
),
body: provider.filteredFacts.isEmpty
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.note_add, size: 48, color: Colors.grey.shade600),
const SizedBox(height: 16),
Text(
'No facts in this category yet',
style: TextStyle(
color: Colors.grey.shade400,
fontSize: 18,
),
),
const SizedBox(height: 8),
TextButton(
onPressed: () => showFactDialog(context, provider),
child: const Text('Add your first fact'),
),
],
),
)
: ListView.builder(
padding: const EdgeInsets.all(16),
itemCount: provider.filteredFacts.length,
itemBuilder: (context, index) {
final fact = provider.filteredFacts[index];
return FactItem(
fact: fact,
provider: provider,
onTap: _showQuickEditSheet,
);
},
),
);
});
}

void _showQuickEditSheet(BuildContext context, Fact fact, FactsProvider provider) {
showModalBottomSheet(
context: context,
backgroundColor: Colors.transparent,
isScrollControlled: true,
builder: (context) => FactEditSheet(
fact: fact,
provider: provider,
onDelete: (_, __, ___) {},
),
);
}
}
Loading