Realtime updating works!
This commit is contained in:
parent
dfeb19126e
commit
ca0fe7dd61
24
ltx_flutter/lib/app_properties_bloc.dart
Normal file
24
ltx_flutter/lib/app_properties_bloc.dart
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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);
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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(
|
||||||
|
|||||||
@ -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,6 +35,8 @@ List<Widget> generateHours(entry) {
|
|||||||
|
|
||||||
List reduced = [];
|
List reduced = [];
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
|
|
||||||
|
if (edit) {
|
||||||
for (int val in hours) {
|
for (int val in hours) {
|
||||||
if (reduced.isEmpty) {
|
if (reduced.isEmpty) {
|
||||||
reduced.add({'val': val, 'num': 1, 'hour': counter});
|
reduced.add({'val': val, 'num': 1, 'hour': counter});
|
||||||
@ -48,11 +50,19 @@ List<Widget> generateHours(entry) {
|
|||||||
}
|
}
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
print(reduced);
|
} else {
|
||||||
|
for (int val in hours) {
|
||||||
|
reduced.add({
|
||||||
|
'hour': counter,
|
||||||
|
'val': val,
|
||||||
|
'num': 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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: [
|
||||||
|
e['num'] == 1
|
||||||
|
? Center(
|
||||||
|
child: Text(
|
||||||
|
style:
|
||||||
|
TextStyle(color: category.foregroundColor),
|
||||||
|
hourString(e['hour'])),
|
||||||
|
)
|
||||||
|
: Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 10, bottom: 10),
|
||||||
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
style: TextStyle(color: category.foregroundColor),
|
style: TextStyle(
|
||||||
hourString(e['hour'])),
|
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(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user