thumbnail: Advertize the thumbnail formats at client registration.

This commit is contained in:
Alex Vandiver 2024-07-13 03:16:41 +00:00 committed by Tim Abbott
parent 6c624805ce
commit 556b92810b
9 changed files with 103 additions and 1 deletions

View File

@ -20,6 +20,11 @@ format used by the Zulip server that they are interacting with.
## Changes in Zulip 9.0
**Feature level 273**
* [`POST /register`](/api/register-queue): Added `server_thumbnail_formats`
describing what formats the server will thumbnail images into.
**Feature level 272**
* [`POST /user_uploads`](/api/upload-file): `uri` was renamed

View File

@ -252,6 +252,7 @@ EXEMPT_FILES = make_set(
"web/src/submessage.ts",
"web/src/subscriber_api.ts",
"web/src/theme.ts",
"web/src/thumbnail.ts",
"web/src/timerender.ts",
"web/src/tippyjs.ts",
"web/src/todo_widget.js",

View File

@ -34,7 +34,7 @@ DESKTOP_WARNING_VERSION = "5.9.3"
# new level means in api_docs/changelog.md, as well as "**Changes**"
# entries in the endpoint's documentation in `zulip.yaml`.
API_FEATURE_LEVEL = 272 # Last bumped for "POST /user_uploads"
API_FEATURE_LEVEL = 273 # Last bumped for server_thumbnail_formats
# Bump the minor PROVISION_VERSION to indicate that folks should provision

View File

@ -179,6 +179,14 @@ const one_time_notice_schema = z.object({
type: z.literal("one_time_notice"),
});
export const thumbnail_format_schema = z.object({
name: z.string(),
max_width: z.number(),
max_height: z.number(),
format: z.string(),
animated: z.boolean(),
});
/* We may introduce onboarding step of types other than 'one time notice'
in future. Earlier, we had 'hotspot' and 'one time notice' as the two
types. We can simply do:
@ -374,6 +382,7 @@ const realm_schema = z.object({
stream: z.record(group_permission_setting_schema),
group: z.record(group_permission_setting_schema),
}),
server_thumbnail_formats: z.array(thumbnail_format_schema),
server_typing_started_expiry_period_milliseconds: z.number(),
server_typing_started_wait_period_milliseconds: z.number(),
server_typing_stopped_wait_period_milliseconds: z.number(),

36
web/src/thumbnail.ts Normal file
View File

@ -0,0 +1,36 @@
import type {z} from "zod";
import {realm} from "./state_data";
import type {thumbnail_format_schema} from "./state_data";
type ThumbnailFormat = z.infer<typeof thumbnail_format_schema>;
export const thumbnail_formats: ThumbnailFormat[] = [];
export let preferred_format: ThumbnailFormat;
export let animated_format: ThumbnailFormat;
export function initialize(): void {
// Go looking for the size closest to 300x200, of the smallest format. We assume all browsers
// support webp.
const format_preferences = ["webp", "jpg", "gif"];
const sorted_formats = realm.server_thumbnail_formats.sort((a, b) => {
if (a.max_width !== b.max_width) {
return Math.abs(a.max_width - 300) < Math.abs(b.max_width - 300) ? -1 : 1;
} else if (a.format !== b.format) {
let a_index = format_preferences.indexOf(a.format);
if (a_index === -1) {
a_index = format_preferences.length;
}
let b_index = format_preferences.indexOf(b.format);
if (b_index === -1) {
b_index = format_preferences.length;
}
return a_index - b_index;
}
return 0;
});
preferred_format = sorted_formats.find((format) => !format.animated)!;
animated_format = sorted_formats.find((format) => format.animated)!;
}

View File

@ -126,6 +126,7 @@ import * as stream_topic_history from "./stream_topic_history";
import * as stream_topic_history_util from "./stream_topic_history_util";
import * as sub_store from "./sub_store";
import * as theme from "./theme";
import * as thumbnail from "./thumbnail";
import * as timerender from "./timerender";
import * as tippyjs from "./tippyjs";
import * as topic_list from "./topic_list";
@ -426,6 +427,7 @@ export function initialize_everything(state_data) {
if (page_params.is_spectator) {
theme.initialize_theme_for_spectator();
}
thumbnail.initialize();
widgets.initialize();
tippyjs.initialize();
compose_tooltips.initialize();

View File

@ -54,6 +54,7 @@ from zerver.lib.subscription_info import (
gather_subscriptions_helper,
get_web_public_subs,
)
from zerver.lib.thumbnail import THUMBNAIL_OUTPUT_FORMATS
from zerver.lib.timestamp import datetime_to_timestamp
from zerver.lib.timezone import canonicalize_timezone
from zerver.lib.topic import TOPIC_NAME
@ -381,6 +382,16 @@ def fetch_initial_state_data(
state["password_min_guesses"] = settings.PASSWORD_MIN_GUESSES
state["server_inline_image_preview"] = settings.INLINE_IMAGE_PREVIEW
state["server_inline_url_embed_preview"] = settings.INLINE_URL_EMBED_PREVIEW
state["server_thumbnail_formats"] = [
{
"name": str(thumbnail_format),
"max_width": thumbnail_format.max_width,
"max_height": thumbnail_format.max_height,
"format": thumbnail_format.extension,
"animated": thumbnail_format.animated,
}
for thumbnail_format in THUMBNAIL_OUTPUT_FORMATS
]
state["server_avatar_changes_disabled"] = settings.AVATAR_CHANGES_DISABLED
state["server_name_changes_disabled"] = settings.NAME_CHANGES_DISABLED
state["server_web_public_streams_enabled"] = settings.WEB_PUBLIC_STREAMS_ENABLED

View File

@ -16397,6 +16397,43 @@ paths:
Clients containing administrative UI for changing
`realm_inline_url_embed_preview` should consult this field before offering
that feature.
server_thumbnail_formats:
description: |
A list describing the image formats that uploaded
images will be thumbnailed into. Any image with a
source starting with `/user_uploads/thumbnail/` can
have its last path component replaced with any of the
names contained in this list, to obtain the desired
thumbnail size.
**Changes**: New in Zulip 9.0 (feature level 273).
type: array
items:
type: object
additionalProperties: false
properties:
name:
type: string
description: |
The file path component of the thumbnail format.
max_width:
type: integer
description: |
The maximum width of this format.
max_height:
type: integer
description: |
The maximum height of this format.
format:
type: string
description: |
The extension of this format.
animated:
type: boolean
description: |
If this file format is animated. These formats
are only generated for uploaded imates which
themselves are animated.
server_avatar_changes_disabled:
type: boolean
description: |

View File

@ -219,6 +219,7 @@ class HomeTest(ZulipTestCase):
"server_presence_offline_threshold_seconds",
"server_presence_ping_interval_seconds",
"server_supported_permission_settings",
"server_thumbnail_formats",
"server_timestamp",
"server_typing_started_expiry_period_milliseconds",
"server_typing_started_wait_period_milliseconds",