feat: add gallery feature with database integration and rendering capabilities
Build Android App / build (push) Failing after 2m19s

This commit is contained in:
ImBenji
2026-08-25 11:46:33 +01:00
parent b66b73a3c6
commit 8c2212b563
17 changed files with 2902 additions and 885 deletions
+254
View File
@@ -0,0 +1,254 @@
import "dart:convert";
import "dart:typed_data";
import "package:flutter/foundation.dart";
import "package:quotegen_client/services/quote_api_v2.dart";
import "package:shadcn_flutter/shadcn_flutter.dart";
import "package:shared_preferences/shared_preferences.dart";
class FormProvider extends ChangeNotifier {
String displayName = "";
String handle = "";
String content = "";
bool verified = false;
DateTime date = DateTime.now();
TimeOfDay time = TimeOfDay.now();
Uint8List? avatarImage;
Uint8List? postImage;
String replies = "";
String retweets = "";
String likes = "";
String views = "";
int? savedTimestamp;
void setDisplayName(String v) {
displayName = v;
notifyListeners();
}
void setHandle(String v) {
handle = v;
notifyListeners();
}
void setContent(String v) {
content = v;
notifyListeners();
}
void setVerified(bool v) {
verified = v;
notifyListeners();
}
void setDate(DateTime v) {
date = v;
notifyListeners();
}
void setTime(TimeOfDay v) {
time = v;
notifyListeners();
}
void setAvatarImage(Uint8List? v) {
avatarImage = v;
notifyListeners();
}
void setPostImage(Uint8List? v) {
postImage = v;
notifyListeners();
}
void setReplies(String v) {
replies = v;
notifyListeners();
}
void setRetweets(String v) {
retweets = v;
notifyListeners();
}
void setLikes(String v) {
likes = v;
notifyListeners();
}
void setViews(String v) {
views = v;
notifyListeners();
}
void setSavedTimestamp(int? v) {
savedTimestamp = v;
notifyListeners();
}
// auto-fill empty engagement fields with "1" if any have a value
// returns true if anything was filled
bool fillEmptyEngagement() {
bool hasValue = replies != "" || retweets != "" || likes != "" || views != "";
bool didFill = false;
if (hasValue) {
if (replies == "") { replies = "1"; didFill = true; }
if (retweets == "") { retweets = "1"; didFill = true; }
if (likes == "") { likes = "1"; didFill = true; }
if (views == "") { views = "1"; didFill = true; }
}
if (didFill) notifyListeners();
return didFill;
}
int combineDateTime() {
DateTime combined = DateTime(
date.year,
date.month,
date.day,
time.hour,
time.minute,
);
return combined.millisecondsSinceEpoch ~/ 1000;
}
int? _parseNum(String val) {
if (val.isEmpty) return null;
return int.tryParse(val.replaceAll(",", ""));
}
QuoteEngagement? buildEngagement(String field) {
if (field == "engagement") {
if (likes == "" && retweets == "" && replies == "" && views == "") {
return null;
}
return QuoteEngagement(
likes: _parseNum(likes),
retweets: _parseNum(retweets),
replies: _parseNum(replies),
views: _parseNum(views),
);
}
return QuoteEngagement(
likes: field == "engagement_likes" ? _parseNum(likes) : null,
retweets: field == "engagement_retweets" ? _parseNum(retweets) : null,
replies: field == "engagement_replies" ? _parseNum(replies) : null,
views: field == "engagement_views" ? _parseNum(views) : null,
);
}
QuoteSessionRequest buildFullRequest() {
QuoteEngagement? engagement;
if (likes != "" || retweets != "" || replies != "" || views != "") {
engagement = QuoteEngagement(
likes: _parseNum(likes),
retweets: _parseNum(retweets),
replies: _parseNum(replies),
views: _parseNum(views),
);
}
return QuoteSessionRequest(
displayName: displayName,
username: handle.toLowerCase(),
text: content,
timestamp: combineDateTime(),
verified: verified,
avatarUrl: avatarImage,
imageUrl: postImage,
engagement: engagement,
);
}
// load form data from shared prefs
Future<void> loadFormData() async {
try {
final prefs = await SharedPreferences.getInstance();
final dn = prefs.getString("display_name") ?? "";
final h = prefs.getString("handle") ?? "";
final c = prefs.getString("content") ?? "";
final ts = prefs.getInt("timestamp") ?? 0;
final rep = prefs.getString("replies") ?? "";
final ret = prefs.getString("retweets") ?? "";
final lk = prefs.getString("likes") ?? "";
final vw = prefs.getString("views") ?? "";
final ver = prefs.getBool("verified") ?? false;
if (ts > 0) savedTimestamp = ts;
Uint8List? avatarImg;
Uint8List? postImg;
String? avatarBase64 = prefs.getString("avatar_image");
if (avatarBase64 != null && avatarBase64.isNotEmpty) {
avatarImg = base64Decode(avatarBase64);
}
String? postBase64 = prefs.getString("post_image");
if (postBase64 != null && postBase64.isNotEmpty) {
postImg = base64Decode(postBase64);
}
print("Loaded form data: name=$dn, handle=$h");
displayName = dn;
handle = h;
content = c;
verified = ver;
replies = rep;
retweets = ret;
likes = lk;
views = vw;
avatarImage = avatarImg;
postImage = postImg;
notifyListeners();
} catch (e) {
print("Error loading form data: $e");
}
}
Future<void> saveFormData() async {
try {
final prefs = await SharedPreferences.getInstance();
print("Saving form data: name=$displayName, handle=$handle");
int tsMillis = combineDateTime() * 1000;
await prefs.setString("display_name", displayName);
await prefs.setString("handle", handle);
await prefs.setString("content", content);
await prefs.setInt("timestamp", tsMillis);
await prefs.setString("replies", replies);
await prefs.setString("retweets", retweets);
await prefs.setString("likes", likes);
await prefs.setString("views", views);
await prefs.setBool("verified", verified);
if (avatarImage != null) {
await prefs.setString("avatar_image", base64Encode(avatarImage!));
} else {
await prefs.remove("avatar_image");
}
if (postImage != null) {
await prefs.setString("post_image", base64Encode(postImage!));
} else {
await prefs.remove("post_image");
}
print("Form data saved");
} catch (e) {
print("Error savin form data: $e");
}
}
}