MagicStarterSupportController class

Backs the support desk screens: the opener's conversation list, one thread, and the three writes that touch a thread.

Why this controller does NOT use MagicStateMixin

The list and the thread are two independent reads on one singleton. The mixin holds a single state slot that setLoading() nulls, so opening a thread would blank the list behind it. Each read publishes its own field and status instead and notifies through refreshUI, the shape MagicStarterBillingController documents.

Tenant boundary

The client never sends a team or user id: the backend scopes every endpoint to the authenticated opener. The rows cached here belong to one session, so the controller is SessionScoped and a sign-in drops them before anything else renders.

Inheritance

Properties

articleSuggestions → List<MagicStarterSupportArticle>
The articles suggested for what the customer is writing, at most three. Empty while nothing is suggested, which includes a failed lookup.
no setter
conversation → MagicStarterSupportConversation?
The thread last read, with its messages. Null before the first read and whenever threadStatus is not loaded.
no setter
conversations → List<MagicStarterSupportConversation>
The signed-in user's own conversations, newest activity first as the backend orders them. Every page loaded so far, concatenated.
no setter
firstError → String?
Get the first validation error message.
no setterinherited
hasErrors → bool
Check if there are any validation errors.
no setterinherited
hashCode → int
The hash code for this object.
no setterinherited
hasListeners → bool
Whether any listeners are currently registered.
no setterinherited
hasMoreConversations → bool
Whether the backend has a page beyond the last one loaded.
no setter
initialized → bool
Whether the controller has been initialized.
no setterinherited
isAwaitingAi → bool
Whether the AI still owes the open thread an answer, for the typing indicator. False when no thread is loaded.
no setter
isDisposed → bool
Whether the controller has been disposed.
no setterinherited
isLoadingMoreConversations → bool
Whether loadMoreConversations has a page in flight.
no setter
isSubmitting → bool
Whether a create, reply or seen write is in flight.
no setter
listStatus → MagicStarterSupportReadStatus
no setter
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited
threadStatus → MagicStarterSupportReadStatus
no setter
topics → List<String>
The topics a new conversation can be filed under, in display order (magic_starter.support.topics).
no setter
validationErrors ↔ Map<String, String>
Current validation errors keyed by field name.
getter/setter pairinherited
viewerName → String?
The signed-in customer's display name, for the avatar of their own rows.
no setter
writeError → String?
The message of the last write the backend refused for a reason other than validation (field errors live in getError). Cleared by the next write.
no setter

Methods

addListener(VoidCallback listener) → void
Register a closure to be called when the object changes.
inherited
attachmentHeaders() → Future<Map<String, String>>
The headers an attachment read needs. An attachment answers only to the bearer token, so a widget loading one passes these along with the url. Empty when nobody is signed in.
Asks for a 60 second signed url to open the PDF attachmentId of conversationId in the system viewer, or null when the backend refused.
authorize(String ability, [Object? arguments]) → void
Authorize an action against the current Auth.user via the Gate.
inherited
clearErrors() → void
Clear all validation errors.
inherited
clearFieldError(String field) → void
Clear a specific field's validation error.
inherited
createConversation({required String body, required String source, String? topic, String? subject, List<MagicFile> attachments = const <MagicFile>[], MagicFile? screenshot, Map<String, String>? clientContext}) → Future<MagicStarterSupportConversation?>
Opens a conversation and answers it, or null when the backend refused (field errors are in getError, anything else in writeError).
dispose() → void
Runs onClose if it has not run yet, then releases the notifier.
inherited
errorFieldFor(String wireKey) → String
Map a raw wire validation key to the form field it should report on.
inherited
forgetArticleSuggestions({bool notify = true}) → void
Drops the suggestions and abandons any lookup still in flight, so what it finds later is not shown. notify false is for a screen's onInit, which runs while the screen is being built (see forgetWriteError).
forgetWriteError() → void
Forgets the last write refusal without notifying, for a screen's onInit: magic's view clears field errors there itself, but writeError is this controller's own and would otherwise greet the next screen. Silent because it runs while the screen is being built.
getError(String field) → String?
Get the validation error message for a field.
inherited
handleApiError(MagicResponse response, {String? fallback}) → void
Handle API error response automatically.
inherited
hasError(String field) → bool
Check if a field has a validation error.
inherited
loadConversation(Object id) → Future<void>
Reads one thread with its messages.
loadConversations() → Future<void>
Reads the signed-in user's conversations from page 1, and arms loadMoreConversations for the pages behind them.
loadMoreConversations() → Future<void>
Appends the page after the last one loaded. Does nothing while a page or a full reread is already in flight, or when hasMoreConversations is false.
markSeen(Object id) → Future<bool>
Tells the backend the customer has read id. Quiet by design: a seen receipt that fails is logged and never shown, only a 404 changes state.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
notifyListeners() → void
Call all the registered listeners.
inherited
onClose() → void
Called when the controller is about to be disposed.
inherited
onInit() → void
Called when the controller is first created.
inherited
rate(Object id, String rating, {String? comment}) → Future<bool>
Rates the resolved conversation id (up or down) and answers whether the backend accepted it. The backend answers 422 for a conversation that is not resolved; that lands in getError under rating.
refreshUI() → void
Refresh the UI by notifying listeners.
inherited
removeListener(VoidCallback listener) → void
Remove a previously registered closure from the list of closures that are notified when the object changes.
inherited
resetForSession() → Future<void>
Drops every row of the previous session, then refetches the list when one had been read (see SessionScoped).
sendMessage(Object id, String body, {List<MagicFile> attachments = const <MagicFile>[]}) → Future<bool>
Posts a reply to id and appends it to the loaded thread. Answers whether the backend accepted it.
setErrorsFromMap(Map<String, List<String>> errors) → void
Set validation errors from a raw wire error map, keyed by errorFieldFor.
inherited
setErrorsFromResponse(MagicResponse response) → void
Set validation errors from an API response.
inherited
suggestArticles(String search) → Future<void>
Looks up articles for search in the app's locale and publishes them as articleSuggestions.
toString() → String
A string representation of this object.
inherited
validate(Map<String, dynamic> data, Map<String, List<Rule>> rules, {Map<String, String> attributes = const <String, String>{}}) → Map<String, dynamic>
Validate the given data against the rules.
inherited
validateRequest(FormRequest request, Map<String, dynamic> data) → Map<String, dynamic>
Run a FormRequest through this mixin's error bag instead of FormRequest.validate().
inherited
validateRequestAsync(FormRequest request, Map<String, dynamic> data) → Future<Map<String, dynamic>>
Same contract as validateRequest, but validates through Validator.validateAsync so any AsyncRule in request's rules actually runs.
inherited

Operators

operator ==(Object other) → bool
The equality operator.
inherited

Static Properties

instance → MagicStarterSupportController
Singleton accessor. Use this instead of constructing directly.
no setter