Merge pull request #102 from LINUXexpert-org/say-why-subscribe-failed
Say so when the server refuses a subscribe
This commit is contained in:
@@ -3,6 +3,7 @@ import { CAP, client, setErrorMessage } from "@/jmap/client";
|
|||||||
import type { BusyPeriod, Calendar, CalendarEvent, GetResponse, Id, JSCalendarParticipant, JSCalendarRecurrenceRule, ParticipantIdentity, QueryResponse, SetResponse } from "@/jmap/types";
|
import type { BusyPeriod, Calendar, CalendarEvent, GetResponse, Id, JSCalendarParticipant, JSCalendarRecurrenceRule, ParticipantIdentity, QueryResponse, SetResponse } from "@/jmap/types";
|
||||||
import { toUTCDate, toLocalDateTime, zonedToDate, parseDuration, DAY_MS, browserTimeZone } from "@/lib/dates";
|
import { toUTCDate, toLocalDateTime, zonedToDate, parseDuration, DAY_MS, browserTimeZone } from "@/lib/dates";
|
||||||
import { settings } from "./settings";
|
import { settings } from "./settings";
|
||||||
|
import { toast } from "@/ui/toast";
|
||||||
import { useSession } from "./session";
|
import { useSession } from "./session";
|
||||||
|
|
||||||
export interface EventInstance {
|
export interface EventInstance {
|
||||||
@@ -146,10 +147,15 @@ export const useCalendar = create<CalendarState>((set, get) => ({
|
|||||||
},
|
},
|
||||||
|
|
||||||
async setSharedSubscribed(accountId, calendarId, subscribed) {
|
async setSharedSubscribed(accountId, calendarId, subscribed) {
|
||||||
|
// See the note in the contacts store: subscribing writes to another
|
||||||
|
// account, so a refusal is an ordinary answer and arrives in `notUpdated`
|
||||||
|
// rather than as a thrown error.
|
||||||
try {
|
try {
|
||||||
await client.call("Calendar/set", { accountId, update: { [calendarId]: { isSubscribed: subscribed } } });
|
const res = await client.call<SetResponse>("Calendar/set", { accountId, update: { [calendarId]: { isSubscribed: subscribed } } });
|
||||||
|
const err = res.notUpdated?.[calendarId];
|
||||||
|
if (err) throw new Error(setErrorMessage(err));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
set({ error: (err as Error).message });
|
toast.error(`Could not ${subscribed ? "add" : "remove"} that calendar: ${(err as Error).message}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
set((s) => ({
|
set((s) => ({
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { create } from "zustand";
|
|||||||
import { CAP, client, setErrorMessage } from "@/jmap/client";
|
import { CAP, client, setErrorMessage } from "@/jmap/client";
|
||||||
import type { AddressBook, ContactCard, EmailAddress, GetResponse, Id, Principal, QueryResponse, SetResponse } from "@/jmap/types";
|
import type { AddressBook, ContactCard, EmailAddress, GetResponse, Id, Principal, QueryResponse, SetResponse } from "@/jmap/types";
|
||||||
import { contactDisplayName, contactEmails, sortKey } from "@/lib/contacts";
|
import { contactDisplayName, contactEmails, sortKey } from "@/lib/contacts";
|
||||||
|
import { toast } from "@/ui/toast";
|
||||||
import { useSession } from "./session";
|
import { useSession } from "./session";
|
||||||
import { useMail } from "./mail";
|
import { useMail } from "./mail";
|
||||||
|
|
||||||
@@ -166,10 +167,20 @@ export const useContacts = create<ContactsState>((set, get) => ({
|
|||||||
},
|
},
|
||||||
|
|
||||||
async setBookSubscribed(accountId, bookId, subscribed) {
|
async setBookSubscribed(accountId, bookId, subscribed) {
|
||||||
|
/*
|
||||||
|
* `notUpdated` matters more here than anywhere else this pattern is used.
|
||||||
|
* Subscribing is a write to somebody *else's* account, so it is the one
|
||||||
|
* call in the app that a perfectly healthy server is entitled to refuse --
|
||||||
|
* and a refusal arrives as a successful response carrying a per-object
|
||||||
|
* failure, not as a thrown error. Ignoring it made a refused subscribe look
|
||||||
|
* exactly like a button that does nothing.
|
||||||
|
*/
|
||||||
try {
|
try {
|
||||||
await client.call("AddressBook/set", { accountId, update: { [bookId]: { isSubscribed: subscribed } } });
|
const res = await client.call<SetResponse>("AddressBook/set", { accountId, update: { [bookId]: { isSubscribed: subscribed } } });
|
||||||
|
const err = res.notUpdated?.[bookId];
|
||||||
|
if (err) throw new Error(setErrorMessage(err));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
set({ error: (err as Error).message });
|
toast.error(`Could not ${subscribed ? "add" : "remove"} that address book: ${(err as Error).message}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!subscribed && get().selection.accountId === accountId && get().selection.bookId === bookId) {
|
if (!subscribed && get().selection.accountId === accountId && get().selection.bookId === bookId) {
|
||||||
|
|||||||
Reference in New Issue
Block a user