init
This commit is contained in:
+201
@@ -0,0 +1,201 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'api/support_api.dart';
|
||||
import 'models/api_exception.dart';
|
||||
import 'models/support_message.dart';
|
||||
import 'models/support_ticket.dart';
|
||||
|
||||
enum TicketStatusFilter { open, closed, all }
|
||||
|
||||
class InboxController extends ChangeNotifier {
|
||||
InboxController({required this.api});
|
||||
|
||||
final SupportApi api;
|
||||
|
||||
TicketStatusFilter statusFilter = TicketStatusFilter.open;
|
||||
String? category;
|
||||
|
||||
List<SupportTicket> tickets = [];
|
||||
bool loading = false;
|
||||
String? error;
|
||||
|
||||
String? activeTicketId;
|
||||
SupportTicket? threadTicket;
|
||||
List<SupportMessage> messages = [];
|
||||
bool threadLoading = false;
|
||||
String? threadError;
|
||||
|
||||
int _listGeneration = 0;
|
||||
int _threadGeneration = 0;
|
||||
|
||||
String? get statusQuery {
|
||||
switch (statusFilter) {
|
||||
case TicketStatusFilter.open:
|
||||
return 'open';
|
||||
case TicketStatusFilter.closed:
|
||||
return 'closed';
|
||||
case TicketStatusFilter.all:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> refreshList({bool showLoading = false}) async {
|
||||
final generation = ++_listGeneration;
|
||||
if (showLoading) {
|
||||
loading = true;
|
||||
error = null;
|
||||
notifyListeners();
|
||||
}
|
||||
try {
|
||||
final next = await api.listTickets(
|
||||
status: statusQuery,
|
||||
category: category,
|
||||
);
|
||||
if (generation != _listGeneration) {
|
||||
return;
|
||||
}
|
||||
tickets = next;
|
||||
error = null;
|
||||
} on ApiException catch (caught) {
|
||||
if (generation != _listGeneration || caught.isUnauthorized) {
|
||||
return;
|
||||
}
|
||||
error = caught.message;
|
||||
} finally {
|
||||
if (generation == _listGeneration) {
|
||||
loading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> refreshThread({bool showLoading = false}) async {
|
||||
final ticketId = activeTicketId;
|
||||
if (ticketId == null) {
|
||||
return;
|
||||
}
|
||||
final generation = ++_threadGeneration;
|
||||
if (showLoading) {
|
||||
threadLoading = true;
|
||||
threadError = null;
|
||||
notifyListeners();
|
||||
}
|
||||
try {
|
||||
final thread = await api.getThread(ticketId);
|
||||
if (generation != _threadGeneration || activeTicketId != ticketId) {
|
||||
return;
|
||||
}
|
||||
_applyThread(thread);
|
||||
threadError = null;
|
||||
} on ApiException catch (caught) {
|
||||
if (generation != _threadGeneration || caught.isUnauthorized) {
|
||||
return;
|
||||
}
|
||||
threadError = caught.message;
|
||||
} finally {
|
||||
if (generation == _threadGeneration) {
|
||||
threadLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> sendReply(String raw) async {
|
||||
final ticketId = activeTicketId;
|
||||
if (ticketId == null) {
|
||||
return 'No ticket is open.';
|
||||
}
|
||||
final validation = validateReplyBody(raw);
|
||||
if (validation != null) {
|
||||
return validation;
|
||||
}
|
||||
final generation = ++_threadGeneration;
|
||||
try {
|
||||
final thread = await api.reply(ticketId, raw.trim());
|
||||
if (generation != _threadGeneration || activeTicketId != ticketId) {
|
||||
return null;
|
||||
}
|
||||
_applyThread(thread);
|
||||
threadError = null;
|
||||
notifyListeners();
|
||||
return null;
|
||||
} on ApiException catch (caught) {
|
||||
if (caught.isUnauthorized) {
|
||||
return null;
|
||||
}
|
||||
return caught.message;
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> setStatus(String status) async {
|
||||
final ticketId = activeTicketId;
|
||||
if (ticketId == null) {
|
||||
return 'No ticket is open.';
|
||||
}
|
||||
final generation = ++_threadGeneration;
|
||||
try {
|
||||
final thread = await api.setStatus(ticketId, status);
|
||||
if (generation != _threadGeneration || activeTicketId != ticketId) {
|
||||
return null;
|
||||
}
|
||||
_applyThread(thread);
|
||||
threadError = null;
|
||||
notifyListeners();
|
||||
return null;
|
||||
} on ApiException catch (caught) {
|
||||
if (caught.isUnauthorized) {
|
||||
return null;
|
||||
}
|
||||
return caught.message;
|
||||
}
|
||||
}
|
||||
|
||||
void setStatusFilter(TicketStatusFilter value) {
|
||||
if (statusFilter == value) {
|
||||
return;
|
||||
}
|
||||
statusFilter = value;
|
||||
tickets = [];
|
||||
unawaited(refreshList(showLoading: true));
|
||||
}
|
||||
|
||||
void setCategory(String? value) {
|
||||
final next = (value == null || value.isEmpty) ? null : value;
|
||||
if (category == next) {
|
||||
return;
|
||||
}
|
||||
category = next;
|
||||
tickets = [];
|
||||
unawaited(refreshList(showLoading: true));
|
||||
}
|
||||
|
||||
void reset() {
|
||||
_listGeneration++;
|
||||
_threadGeneration++;
|
||||
statusFilter = TicketStatusFilter.open;
|
||||
category = null;
|
||||
tickets = [];
|
||||
loading = false;
|
||||
error = null;
|
||||
activeTicketId = null;
|
||||
threadTicket = null;
|
||||
messages = [];
|
||||
threadLoading = false;
|
||||
threadError = null;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void _applyThread(SupportThread thread) {
|
||||
threadTicket = thread.ticket;
|
||||
messages = thread.messages;
|
||||
final index = tickets.indexWhere((ticket) => ticket.id == thread.ticket.id);
|
||||
if (index >= 0) {
|
||||
tickets = [
|
||||
for (var i = 0; i < tickets.length; i++)
|
||||
if (i == index) thread.ticket else tickets[i],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user