Realtime updating works!

This commit is contained in:
Ryan Pandya 2023-06-03 16:36:01 -04:00
parent dfeb19126e
commit ca0fe7dd61
6 changed files with 175 additions and 45 deletions

View File

@ -0,0 +1,24 @@
import 'dart:async';
final appBloc = AppPropertiesBloc();
class AppPropertiesBloc {
StreamController<String> _title = StreamController<String>();
StreamController<bool> _editable = StreamController<bool>();
Stream<String> get titleStream => _title.stream;
Stream<bool> get editable => _editable.stream;
updateTitle(String newTitle) {
_title.sink.add(newTitle);
}
toggleEditable(bool editable) {
_editable.sink.add(!editable);
}
dispose() {
_title.close();
_editable.close();
}
}

View File

@ -50,7 +50,7 @@ class Category {
} }
Color _getForegroundColor(String colorStr) { Color _getForegroundColor(String colorStr) {
return Color(int.parse("0xff$colorStr")).computeLuminance() > 0.5 return Color(int.parse("0xff$colorStr")).computeLuminance() > 0.2
? Colors.black ? Colors.black
: Colors.white; : Colors.white;
} }
@ -99,7 +99,6 @@ class CategoriesAPI extends ChangeNotifier {
if (!_ready) { if (!_ready) {
return false; return false;
} }
print(_ready);
return Category(_categories.singleWhere((e) { return Category(_categories.singleWhere((e) {
return e.data['number'] == double.parse(n.toString()); return e.data['number'] == double.parse(n.toString());
})); }));
@ -174,7 +173,6 @@ class CategoriesAPI extends ChangeNotifier {
'parent': parentId, 'parent': parentId,
'description': description, 'description': description,
}); });
print(x);
return x; return x;
} catch (e) { } catch (e) {
print(e); print(e);

View File

@ -4,11 +4,13 @@ import 'package:flutter/material.dart';
import 'package:ltx_flutter/appwrite/auth_api.dart'; import 'package:ltx_flutter/appwrite/auth_api.dart';
import 'package:ltx_flutter/constants/constants.dart'; import 'package:ltx_flutter/constants/constants.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:ltx_flutter/constants/constants.dart';
class DatabaseAPI extends ChangeNotifier { class DatabaseAPI extends ChangeNotifier {
Client client = Client(); Client client = Client();
late final Account account; late final Account account;
late final Databases databases; late final Databases databases;
late final Realtime realtime;
final AuthAPI auth = AuthAPI(); final AuthAPI auth = AuthAPI();
late List<Document> _entries = []; late List<Document> _entries = [];
@ -26,15 +28,52 @@ class DatabaseAPI extends ChangeNotifier {
DatabaseAPI() { DatabaseAPI() {
init(); init();
getAll(); getAll();
subscribeRealtime();
} }
init() { init() {
client client.setEndpoint(APPWRITE_URL).setProject(APPWRITE_PROJECT_ID);
.setEndpoint(APPWRITE_URL)
.setProject(APPWRITE_PROJECT_ID)
.setSelfSigned();
account = Account(client); account = Account(client);
databases = Databases(client); databases = Databases(client);
realtime = Realtime(client);
}
elDate(dynamic el) {
return formatter.format(DateTime.parse(el.data['date']));
}
sortByDate(entries) {
return entries.sort(
(a, b) => a.$id.compareTo(b.$id),
);
}
subscribeRealtime() {
final subscription = realtime.subscribe(
['databases.$APPWRITE_DATABASE_ID.collections.$COLLECTION.documents']);
print("Subscribed to realtime");
subscription.stream.listen((response) {
String dateISO =
formatter.format(DateTime.parse(response.payload['date']));
if (response.events.contains(
'databases.$APPWRITE_DATABASE_ID.collections.$COLLECTION.documents.*.update')) {
// Entry was updated
int entryIndex =
_entries.indexWhere((element) => elDate(element) == dateISO);
Document newEntry = _entries[entryIndex];
newEntry.data['hours'] = response.payload['hours'];
newEntry.data['mood'] = response.payload['mood'];
newEntry.data['comments'] = response.payload['comments'];
_entries.removeAt(entryIndex);
_entries.add(newEntry);
notifyListeners();
// _entries.add(entry);
// sortByDate(_entries);
}
});
} }
int total() { int total() {
@ -81,9 +120,7 @@ class DatabaseAPI extends ChangeNotifier {
); );
_entries.add(response.first); _entries.add(response.first);
_entries.sort(
(a, b) => a.$id.compareTo(b.$id),
);
notifyListeners(); notifyListeners();
return response.first; return response.first;
} }

View File

@ -25,6 +25,7 @@ class LifetrackerApp extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final loginStatus = context.watch<AuthAPI>().status; final loginStatus = context.watch<AuthAPI>().status;
return MaterialApp( return MaterialApp(
debugShowCheckedModeBanner: false,
scrollBehavior: const MaterialScrollBehavior().copyWith(dragDevices: { scrollBehavior: const MaterialScrollBehavior().copyWith(dragDevices: {
PointerDeviceKind.mouse, PointerDeviceKind.mouse,
PointerDeviceKind.touch, PointerDeviceKind.touch,

View File

@ -2,6 +2,7 @@ import 'package:ltx_flutter/pages/account_page.dart';
import 'package:ltx_flutter/pages/categories_page.dart'; import 'package:ltx_flutter/pages/categories_page.dart';
import 'package:ltx_flutter/pages/today_page.dart'; import 'package:ltx_flutter/pages/today_page.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../app_properties_bloc.dart';
class TabsPage extends StatefulWidget { class TabsPage extends StatefulWidget {
const TabsPage({Key? key}) : super(key: key); const TabsPage({Key? key}) : super(key: key);
@ -25,7 +26,33 @@ class _TabsPageState extends State<TabsPage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text("Flutter"), title: StreamBuilder<Object>(
stream: appBloc.titleStream,
initialData: "Flutter",
builder: (context, snapshot) {
return Text(snapshot.data.toString());
}),
actions: [
Padding(
padding: const EdgeInsets.only(right: 28.0),
child: Row(
children: [
Text("Edit"),
StreamBuilder<Object>(
stream: appBloc.editable,
initialData: true,
builder: (context, snapshot) {
return Switch(
value: bool.parse(snapshot.data.toString()),
onChanged: (value) {
// print(value);
},
);
}),
],
),
)
],
), ),
body: _widgets.elementAt(_selectedIndex), body: _widgets.elementAt(_selectedIndex),
bottomNavigationBar: BottomNavigationBar( bottomNavigationBar: BottomNavigationBar(

View File

@ -25,7 +25,7 @@ String hourString(int e) {
return "${hour.toString()} $meridien"; return "${hour.toString()} $meridien";
} }
List<Widget> generateHours(entry) { List<Widget> generateHours(entry, bool edit) {
if (entry == null) { if (entry == null) {
return [Center(child: RefreshProgressIndicator())]; return [Center(child: RefreshProgressIndicator())];
} }
@ -35,24 +35,34 @@ List<Widget> generateHours(entry) {
List reduced = []; List reduced = [];
int counter = 0; int counter = 0;
for (int val in hours) {
if (reduced.isEmpty) { if (edit) {
reduced.add({'val': val, 'num': 1, 'hour': counter}); for (int val in hours) {
} else { if (reduced.isEmpty) {
if (reduced.last['val'] == val) {
reduced.last['num']++;
reduced.last['hour'] = counter;
} else {
reduced.add({'val': val, 'num': 1, 'hour': counter}); reduced.add({'val': val, 'num': 1, 'hour': counter});
} else {
if (reduced.last['val'] == val) {
reduced.last['num']++;
reduced.last['hour'] = counter;
} else {
reduced.add({'val': val, 'num': 1, 'hour': counter});
}
} }
counter++;
}
} else {
for (int val in hours) {
reduced.add({
'hour': counter,
'val': val,
'num': 1,
});
} }
counter++;
} }
print(reduced);
return reduced.map( return reduced.map(
(e) { (e) {
double height = double.parse((e['num'] * 35).toString()); double height = double.parse((e['num'] * 36).toString());
return Consumer<CategoriesAPI>( return Consumer<CategoriesAPI>(
builder: (context, categories, child) { builder: (context, categories, child) {
Category category = categories.lookUp(e['val'].toString()); Category category = categories.lookUp(e['val'].toString());
@ -63,10 +73,38 @@ List<Widget> generateHours(entry) {
child: Padding( child: Padding(
padding: const EdgeInsets.only(left: 10), padding: const EdgeInsets.only(left: 10),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( e['num'] == 1
style: TextStyle(color: category.foregroundColor), ? Center(
hourString(e['hour'])), child: Text(
style:
TextStyle(color: category.foregroundColor),
hourString(e['hour'])),
)
: Padding(
padding: const EdgeInsets.only(top: 10, bottom: 10),
child: Column(
children: [
Text(
style: TextStyle(
color: category.foregroundColor),
hourString(e['hour'] - e['num'] + 1)),
Expanded(
child: VerticalDivider(
indent: 10,
endIndent: 10,
color: category.foregroundColor,
width: 4,
),
),
Text(
style: TextStyle(
color: category.foregroundColor),
hourString(e['hour'] + 1))
],
),
),
Expanded( Expanded(
child: Center( child: Center(
child: Text( child: Text(
@ -85,6 +123,26 @@ List<Widget> generateHours(entry) {
).toList(); ).toList();
} }
Color moodColor(mood) {
if (mood == null) {
return Colors.transparent;
}
if (mood >= 8) {
return Colors.green;
}
if (mood > 5) {
return Colors.blue;
}
if (mood == 5) {
return Colors.yellow;
}
if (mood >= 3) {
return Colors.amber;
} else {
return Colors.red;
}
}
class TodayPage extends StatefulWidget { class TodayPage extends StatefulWidget {
const TodayPage({Key? key}) : super(key: key); const TodayPage({Key? key}) : super(key: key);
@ -175,7 +233,6 @@ class _DayViewState extends State<DayView> {
super.didChangeDependencies(); super.didChangeDependencies();
database = context.watch<DatabaseAPI>(); database = context.watch<DatabaseAPI>();
categories = context.watch<CategoriesAPI>(); categories = context.watch<CategoriesAPI>();
print(categories.lookUp(9));
entries = database.entries; entries = database.entries;
} }
@ -190,22 +247,6 @@ class _DayViewState extends State<DayView> {
} }
} }
// Document? grabEntry(DateTime date) {
// DatabaseAPI database = context.watch<DatabaseAPI>();
// entries = database.entries;
// String formattedDate = formatDate(
// dateISO: date.toIso8601String(),
// format: "yyyy-MM-dd",
// );
// try {
// dayEntry = entries.singleWhere((element) => element.$id == formattedDate);
// return dayEntry;
// } catch (e) {
// database.getOne(date: formattedDate).then((value) => dayEntry = value);
// }
// }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
List<Document> entries = database.entries; List<Document> entries = database.entries;
@ -292,7 +333,7 @@ class _DayViewState extends State<DayView> {
Expanded( Expanded(
child: ListView( child: ListView(
children: categories.ready children: categories.ready
? generateHours(dayEntry) ? generateHours(dayEntry, true)
: [CircularProgressIndicator()], : [CircularProgressIndicator()],
), ),
), ),
@ -304,7 +345,9 @@ class _DayViewState extends State<DayView> {
SizedBox.square( SizedBox.square(
dimension: 50, dimension: 50,
child: Container( child: Container(
color: Colors.amber, child: Center(child: moodWidget)), color: moodColor(mood),
child: Center(child: moodWidget),
),
), ),
SizedBox(width: 30), SizedBox(width: 30),
Expanded( Expanded(