Refactor note handling to include ID generation and improve initialization logic
This commit is contained in:
@@ -66,7 +66,8 @@ Future<void> runPrimaryInstance(File ipcFile) async {
|
||||
startIpcWatcher(ipcFile);
|
||||
|
||||
// Initialize the app
|
||||
await DB.init();
|
||||
// await DB.init();
|
||||
await init();
|
||||
await windowManager.ensureInitialized();
|
||||
|
||||
WindowOptions windowOptions = const WindowOptions(
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:core';
|
||||
import 'dart:math';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:journaler/notes.dart';
|
||||
|
||||
@@ -7,7 +8,15 @@ const endpoint = 'https://meili.site.quack-lab.dev/';
|
||||
const noteIndex = 'notes';
|
||||
const scratchIndex = 'scratch';
|
||||
const settingsIndex = 'settings';
|
||||
const apiKey = String.fromEnvironment('MEILISEARCH_API_KEY', defaultValue: '');
|
||||
const apiKey = String.fromEnvironment(
|
||||
'MEILISEARCH_API_KEY',
|
||||
defaultValue:
|
||||
'',
|
||||
);
|
||||
const header = {
|
||||
'Authorization': 'Bearer $apiKey',
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
|
||||
class MeilisearchQuery {
|
||||
String q;
|
||||
@@ -82,12 +91,60 @@ class MeilisearchResponse {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> init() async {
|
||||
if (!await indexExists(noteIndex)) {
|
||||
await http.post(
|
||||
Uri.parse('$endpoint/indexes'),
|
||||
headers: header,
|
||||
body: jsonEncode({'uid': noteIndex, 'primaryKey': 'id'}),
|
||||
);
|
||||
await http.put(
|
||||
Uri.parse('$endpoint/indexes/$noteIndex/settings/sortable-attributes'),
|
||||
headers: header,
|
||||
body: jsonEncode({
|
||||
'attributes': ['date'],
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (!await indexExists(scratchIndex)) {
|
||||
await http.post(
|
||||
Uri.parse('$endpoint/indexes'),
|
||||
headers: header,
|
||||
body: jsonEncode({'uid': scratchIndex, 'primaryKey': 'id'}),
|
||||
);
|
||||
await http.put(
|
||||
Uri.parse('$endpoint/indexes/$scratchIndex/settings/sortable-attributes'),
|
||||
headers: header,
|
||||
body: jsonEncode({
|
||||
'attributes': ['date'],
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (!await indexExists(settingsIndex)) {
|
||||
await http.post(
|
||||
Uri.parse('$endpoint/indexes'),
|
||||
headers: header,
|
||||
body: jsonEncode({'uid': settingsIndex, 'primaryKey': 'key'}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> indexExists(String index) async {
|
||||
final response = await http.get(
|
||||
Uri.parse('$endpoint/indexes/$index'),
|
||||
headers: header,
|
||||
);
|
||||
return response.statusCode == 200;
|
||||
}
|
||||
|
||||
// Settings Management
|
||||
Future<String?> getSetting(String key) async {
|
||||
final searchCondition = MeilisearchQuery(q: '', filter: 'key = $key');
|
||||
final response = await http.post(
|
||||
Uri.parse('$endpoint/indexes/$settingsIndex/search'),
|
||||
headers: {'Authorization': 'Bearer $apiKey'},
|
||||
headers: header,
|
||||
body: jsonEncode(searchCondition.toJson()),
|
||||
);
|
||||
if (response.statusCode != 200) {
|
||||
@@ -104,7 +161,7 @@ Future<void> setSetting(String key, String value) async {
|
||||
final document = {'key': key, 'value': value};
|
||||
final response = await http.post(
|
||||
Uri.parse('$endpoint/indexes/$settingsIndex/documents'),
|
||||
headers: {'Authorization': 'Bearer $apiKey'},
|
||||
headers: header,
|
||||
body: jsonEncode(document),
|
||||
);
|
||||
if (response.statusCode != 200) {
|
||||
@@ -125,7 +182,7 @@ Future<List<Note>> searchNotes(String query) async {
|
||||
);
|
||||
final response = await http.post(
|
||||
Uri.parse('$endpoint/indexes/$noteIndex/search'),
|
||||
headers: {'Authorization': 'Bearer $apiKey'},
|
||||
headers: header,
|
||||
body: jsonEncode(searchCondition.toJson()),
|
||||
);
|
||||
if (response.statusCode != 200) {
|
||||
@@ -135,6 +192,7 @@ Future<List<Note>> searchNotes(String query) async {
|
||||
return responseJson.hits
|
||||
.map(
|
||||
(hit) => Note(
|
||||
id: hit['id'] as String,
|
||||
date: hit['date'] as String,
|
||||
content: hit['content'] as String,
|
||||
),
|
||||
@@ -151,7 +209,7 @@ Future<Note?> getPreviousTo(String date) async {
|
||||
);
|
||||
final response = await http.post(
|
||||
Uri.parse('$endpoint/indexes/$noteIndex/search'),
|
||||
headers: {'Authorization': 'Bearer $apiKey'},
|
||||
headers: header,
|
||||
body: jsonEncode(searchCondition.toJson()),
|
||||
);
|
||||
if (response.statusCode != 200) {
|
||||
@@ -162,6 +220,7 @@ Future<Note?> getPreviousTo(String date) async {
|
||||
return null;
|
||||
}
|
||||
return Note(
|
||||
id: responseJson.hits.first['id'] as String,
|
||||
date: responseJson.hits.first['date'] as String,
|
||||
content: responseJson.hits.first['content'] as String,
|
||||
);
|
||||
@@ -176,7 +235,7 @@ Future<Note?> getNextTo(String date) async {
|
||||
);
|
||||
final response = await http.post(
|
||||
Uri.parse('$endpoint/indexes/$noteIndex/search'),
|
||||
headers: {'Authorization': 'Bearer $apiKey'},
|
||||
headers: header,
|
||||
body: jsonEncode(searchCondition.toJson()),
|
||||
);
|
||||
if (response.statusCode != 200) {
|
||||
@@ -187,6 +246,7 @@ Future<Note?> getNextTo(String date) async {
|
||||
return null;
|
||||
}
|
||||
return Note(
|
||||
id: responseJson.hits.first['id'] as String,
|
||||
date: responseJson.hits.first['date'] as String,
|
||||
content: responseJson.hits.first['content'] as String,
|
||||
);
|
||||
@@ -195,12 +255,12 @@ Future<Note?> getNextTo(String date) async {
|
||||
Future<Note?> getLatest() async {
|
||||
final searchCondition = MeilisearchQuery(
|
||||
q: '',
|
||||
sort: ['date DESC'],
|
||||
sort: ['date:desc'],
|
||||
limit: 1,
|
||||
);
|
||||
final response = await http.post(
|
||||
Uri.parse('$endpoint/indexes/$noteIndex/search'),
|
||||
headers: {'Authorization': 'Bearer $apiKey'},
|
||||
headers: header,
|
||||
body: jsonEncode(searchCondition.toJson()),
|
||||
);
|
||||
if (response.statusCode != 200) {
|
||||
@@ -211,11 +271,23 @@ Future<Note?> getLatest() async {
|
||||
return null;
|
||||
}
|
||||
return Note(
|
||||
id: responseJson.hits.first['id'] as String,
|
||||
date: responseJson.hits.first['date'] as String,
|
||||
content: responseJson.hits.first['content'] as String,
|
||||
);
|
||||
}
|
||||
|
||||
String generateRandomString(int length) {
|
||||
const characters =
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
var result = '';
|
||||
for (var i = 0; i < length; i++) {
|
||||
final randomIndex = Random().nextInt(characters.length);
|
||||
result += characters[randomIndex];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<Note> createNote(String content) async {
|
||||
final lines = content.split('\n');
|
||||
final trimmedLines = <String>[];
|
||||
@@ -238,20 +310,22 @@ Future<Note> createNote(String content) async {
|
||||
final mostFrequentLetterCount = letterFrequency[mostFrequentLetter];
|
||||
|
||||
final document = {
|
||||
'id': DateTime.now().toIso8601String(),
|
||||
'id': generateRandomString(32),
|
||||
'date': DateTime.now().toIso8601String(),
|
||||
'content': content,
|
||||
'topLetter': mostFrequentLetter,
|
||||
'topLetterFrequency': mostFrequentLetterCount,
|
||||
};
|
||||
final response = await http.post(
|
||||
Uri.parse('$endpoint/indexes/$noteIndex/documents'),
|
||||
headers: {'Authorization': 'Bearer $apiKey'},
|
||||
headers: header,
|
||||
body: jsonEncode(document),
|
||||
);
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('Failed to create note');
|
||||
}
|
||||
return Note(
|
||||
id: document['id'] as String,
|
||||
date: document['id'] as String,
|
||||
content: document['content'] as String,
|
||||
);
|
||||
@@ -264,7 +338,7 @@ Future<List<Note>> getProblematic({double threshold = 0.7}) async {
|
||||
);
|
||||
final response = await http.post(
|
||||
Uri.parse('$endpoint/indexes/$noteIndex/search'),
|
||||
headers: {'Authorization': 'Bearer $apiKey'},
|
||||
headers: header,
|
||||
body: jsonEncode(searchCondition.toJson()),
|
||||
);
|
||||
if (response.statusCode != 200) {
|
||||
@@ -274,6 +348,7 @@ Future<List<Note>> getProblematic({double threshold = 0.7}) async {
|
||||
return responseJson.hits
|
||||
.map(
|
||||
(hit) => Note(
|
||||
id: hit['id'] as String,
|
||||
date: hit['date'] as String,
|
||||
content: hit['content'] as String,
|
||||
isProblematic: true,
|
||||
@@ -285,10 +360,11 @@ Future<List<Note>> getProblematic({double threshold = 0.7}) async {
|
||||
}
|
||||
|
||||
Future<void> updateNote(String id, String content) async {
|
||||
// TODO: Trim and calculate frequency
|
||||
final document = {'id': id, 'content': content};
|
||||
final response = await http.post(
|
||||
Uri.parse('$endpoint/indexes/$noteIndex/documents'),
|
||||
headers: {'Authorization': 'Bearer $apiKey'},
|
||||
headers: header,
|
||||
body: jsonEncode(document),
|
||||
);
|
||||
if (response.statusCode != 200) {
|
||||
@@ -299,7 +375,7 @@ Future<void> updateNote(String id, String content) async {
|
||||
Future<void> deleteNote(String id) async {
|
||||
final response = await http.delete(
|
||||
Uri.parse('$endpoint/indexes/$noteIndex/documents/$id'),
|
||||
headers: {'Authorization': 'Bearer $apiKey'},
|
||||
headers: header,
|
||||
);
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('Failed to delete note');
|
||||
@@ -314,7 +390,7 @@ Future<Scratch?> getLatestScratch() async {
|
||||
);
|
||||
final response = await http.post(
|
||||
Uri.parse('$endpoint/indexes/$scratchIndex/search'),
|
||||
headers: {'Authorization': 'Bearer $apiKey'},
|
||||
headers: header,
|
||||
body: jsonEncode(searchCondition.toJson()),
|
||||
);
|
||||
if (response.statusCode != 200) {
|
||||
@@ -334,7 +410,7 @@ Future<void> createScratch(String content) async {
|
||||
final document = {'id': DateTime.now().toIso8601String(), 'content': content};
|
||||
final response = await http.post(
|
||||
Uri.parse('$endpoint/indexes/$scratchIndex/documents'),
|
||||
headers: {'Authorization': 'Bearer $apiKey'},
|
||||
headers: header,
|
||||
body: jsonEncode(document),
|
||||
);
|
||||
if (response.statusCode != 200) {
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
class Note {
|
||||
final String id;
|
||||
final String date;
|
||||
late final String displayDate;
|
||||
String content;
|
||||
@@ -9,6 +10,7 @@ class Note {
|
||||
String problemReason;
|
||||
|
||||
Note({
|
||||
required this.id,
|
||||
required this.date,
|
||||
required this.content,
|
||||
this.snippet,
|
||||
|
Reference in New Issue
Block a user