mirror of
https://github.com/mattermost/mattermost-mobile.git
synced 2026-11-07 03:10:12 +00:00
Client, mapping, and capability layer only — intentionally NOT wired into any
lifecycle/trigger path yet (no coordinator, no workers).
- types/api/drafts.d.ts: add DraftApi (server response) and DraftUpsertRequest
(POST body) DTOs alongside DraftProps.
- types/api/config.d.ts: add AllowSyncedDrafts to ClientConfig.
- client/rest/base.ts: add draft route helpers (drafts POST, user/team GET,
channel/thread DELETE).
- client/rest/drafts.ts (+test): ClientDrafts mixin — getDrafts, upsertDraft,
deleteDraft (channel vs thread by rootId), Connection-Id header on POST/DELETE.
Mixed into client/rest/index.ts (also drops a pre-existing duplicate
ClientScheduledPost entry in the .with() list).
- constants/preferences.ts: add ADVANCED_SYNC_DRAFTS ('sync_drafts').
- utils/draft/sync.ts (+test): pure bidirectional normalization. server->mobile
maps update_at->server_update_at (never local update_at), priority, props
passthrough, exact file_ids, files from metadata.files; mobile->server sends
only channel_id/root_id/message/type/props/file_ids/priority and returns null
for an empty message so it never POSTs. Fail-closed burn-on-read reconstruction
(durations come from server config, not props; missing/invalid -> no enabled
borConfig).
- queries/servers/drafts.ts: getIsDraftSyncEnabled / observeIsDraftSyncEnabled —
enabled when AllowSyncedDrafts==='true' AND sync_drafts pref not 'false'
(absent = enabled). No server-version gate.
Checks: npm run tsc clean; eslint --quiet clean; 69 focused Jest tests pass
across the new client/sync suites and the scheduled_post/post-handler/drafts
regression neighbors.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
52 lines
1.7 KiB
TypeScript
52 lines
1.7 KiB
TypeScript
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
import type ClientBase from './base';
|
|
|
|
export interface ClientDraftsMix {
|
|
getDrafts(teamId: string, groupLabel?: RequestGroupLabel): Promise<DraftApi[]>;
|
|
upsertDraft(draft: DraftUpsertRequest, connectionId?: string): Promise<DraftApi>;
|
|
deleteDraft(channelId: string, rootId?: string, connectionId?: string): Promise<DraftApi>;
|
|
}
|
|
|
|
const ClientDrafts = <TBase extends Constructor<ClientBase>>(superclass: TBase) => class extends superclass {
|
|
getDrafts = (teamId: string, groupLabel?: RequestGroupLabel) => {
|
|
return this.doFetch(
|
|
this.getUserTeamDraftsRoute('me', teamId),
|
|
{method: 'get', groupLabel},
|
|
);
|
|
};
|
|
|
|
upsertDraft = (draft: DraftUpsertRequest, connectionId?: string) => {
|
|
const headers: Record<string, string> = {};
|
|
if (connectionId) {
|
|
headers['Connection-Id'] = connectionId;
|
|
}
|
|
return this.doFetch(
|
|
this.getDraftsRoute(),
|
|
{
|
|
method: 'post',
|
|
body: draft,
|
|
headers,
|
|
},
|
|
);
|
|
};
|
|
|
|
deleteDraft = (channelId: string, rootId = '', connectionId?: string) => {
|
|
const headers: Record<string, string> = {};
|
|
if (connectionId) {
|
|
headers['Connection-Id'] = connectionId;
|
|
}
|
|
const route = rootId ? this.getUserThreadDraftRoute('me', channelId, rootId) : this.getUserChannelDraftsRoute('me', channelId);
|
|
return this.doFetch(
|
|
route,
|
|
{
|
|
method: 'delete',
|
|
headers,
|
|
},
|
|
);
|
|
};
|
|
};
|
|
|
|
export default ClientDrafts;
|