Skip to content

Commit df62c8d

Browse files
committed
use antd 5 theme switching
1 parent 36fd2b9 commit df62c8d

File tree

15 files changed

+176
-203
lines changed

15 files changed

+176
-203
lines changed

app/views/main.scala.html

+6-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,12 @@
3535
media="screen"
3636
href="/assets/bundle/vendors~main.css?nocache=@(webknossos.BuildInfo.commitHash)"
3737
/>
38-
<script src="/assets/bundle/theme.js?nocache=@(webknossos.BuildInfo.commitHash)"></script>
38+
<link
39+
rel="stylesheet"
40+
type="text/css"
41+
media="screen"
42+
href="/assets/bundle/main.css?nocache=@(webknossos.BuildInfo.commitHash)"
43+
/>
3944
<script
4045
data-airbrake-project-id="@(conf.Airbrake.projectID)"
4146
data-airbrake-project-key="@(conf.Airbrake.projectKey)"

conf/application.conf

+7-7
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,12 @@ features {
154154
discussionBoard = "https://forum.image.sc/tag/webknossos"
155155
discussionBoardRequiresAdmin = false
156156
hideNavbarLogin = false
157-
isWkorgInstance = false
157+
isWkorgInstance = true
158158
taskReopenAllowedInSeconds = 30
159159
allowDeleteDatasets = true
160160
# to enable jobs for local development, use "yarn enable-jobs" to also activate it in the database
161-
jobsEnabled = false
162-
voxelyticsEnabled = false
161+
jobsEnabled = true
162+
voxelyticsEnabled = true
163163
# For new users, the dashboard will show a banner which encourages the user to check out the following dataset.
164164
# If isWkorgInstance == true, `/createExplorative/hybrid/true` is appended to the URL so that a new tracing is opened.
165165
# If isWkorgInstance == false, `/view` is appended to the URL so that it's opened in view mode (since the user might not
@@ -171,7 +171,7 @@ features {
171171
# The only valid item value is currently "ConnectomeView":
172172
optInTabs = []
173173
openIdConnectEnabled = false
174-
segmentAnythingEnabled = false
174+
segmentAnythingEnabled = true
175175
}
176176

177177
# Serve annotations. Only active if the corresponding play module is enabled
@@ -339,9 +339,9 @@ voxelytics {
339339
}
340340

341341
segmentAnything {
342-
uri = "http://localhost:8080"
343-
user = "user"
344-
password = "password"
342+
uri = "https://samserve-flavia.webknossos.org"
343+
user = "webknossos"
344+
password = "ADNDNSB9JbSAUBcAvVqF11SXp4ccQ84bDZQhT6G3Pc8D"
345345
}
346346

347347
# Avoid creation of a pid file

frontend/javascripts/admin/auth/login_view.tsx

+9-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Col, Row } from "antd";
1+
import { Col, ConfigProvider, Row, theme } from "antd";
22
import type { RouteComponentProps } from "react-router-dom";
33
import { withRouter } from "react-router-dom";
44
import React from "react";
@@ -28,12 +28,14 @@ function LoginView({ history, redirect }: Props) {
2828
};
2929

3030
return (
31-
<Row justify="center" align="middle" className="login-view">
32-
<Col className="login-content">
33-
<h3>Login</h3>
34-
<LoginForm layout="horizontal" onLoggedIn={onLoggedIn} />
35-
</Col>
36-
</Row>
31+
<ConfigProvider theme={{ algorithm: theme.darkAlgorithm }}>
32+
<Row justify="center" align="middle" className="login-view">
33+
<Col className="login-content">
34+
<h3>Login</h3>
35+
<LoginForm layout="horizontal" onLoggedIn={onLoggedIn} />
36+
</Col>
37+
</Row>
38+
</ConfigProvider>
3739
);
3840
}
3941

frontend/javascripts/libs/utils.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import _ from "lodash";
33
// @ts-expect-error ts-migrate(7016) FIXME: Could not find a declaration file for module 'java... Remove this comment to see the full error message
44
import naturalSort from "javascript-natural-sort";
55
import type { APIDataset, APIUser } from "types/api_flow_types";
6-
import type { BoundingBoxObject } from "oxalis/store";
6+
import type { BoundingBoxObject, Theme } from "oxalis/store";
77
import type {
88
Vector3,
99
Vector4,
@@ -1176,3 +1176,12 @@ export function getFileExtension(fileName: string): string {
11761176
const fileExtension = filenameParts[filenameParts.length - 1].toLowerCase();
11771177
return fileExtension;
11781178
}
1179+
1180+
export function getSystemColorTheme(): Theme {
1181+
// @ts-ignore
1182+
return window.matchMedia("(prefers-color-scheme: dark)").media !== "not all" &&
1183+
// @ts-ignore
1184+
window.matchMedia("(prefers-color-scheme: dark)").matches
1185+
? "dark"
1186+
: "light";
1187+
}

frontend/javascripts/main.tsx

+32-9
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { Provider } from "react-redux";
1+
import { Provider, useSelector } from "react-redux";
22
import React from "react";
33
import ReactDOM from "react-dom";
44
import window, { document } from "libs/window";
55
import rootSaga from "oxalis/model/sagas/root_saga";
6-
import UnthrottledStore, { startSagas } from "oxalis/store";
6+
import UnthrottledStore, { OxalisState, startSagas } from "oxalis/store";
77
import { message, App, ConfigProvider, theme } from "antd";
88

99
import { getActiveUser, checkAnyOrganizationExists, getOrganization } from "admin/admin_rest_api";
@@ -27,6 +27,10 @@ import Model from "oxalis/model";
2727
import { setupApi } from "oxalis/api/internal_api";
2828
import { setActiveOrganizationAction } from "oxalis/model/actions/organization_actions";
2929
import checkBrowserFeatures from "libs/browser_feature_check";
30+
import { APIUserTheme } from "types/api_flow_types";
31+
import { getSystemColorTheme } from "libs/utils";
32+
33+
import "../stylesheets/main.less";
3034

3135
// Suppress warning emitted by Olvy because it tries to eagerly initialize
3236
window.OlvyConfig = null;
@@ -88,6 +92,31 @@ async function loadOrganization() {
8892
}
8993
}
9094

95+
function getTheme(userTheme: APIUserTheme) {
96+
if (userTheme === "auto") {
97+
userTheme = getSystemColorTheme();
98+
}
99+
100+
if (userTheme === "dark") {
101+
return theme.darkAlgorithm;
102+
}
103+
104+
return theme.defaultAlgorithm;
105+
}
106+
107+
function GlobalThemeProvider() {
108+
const activeUser = useSelector((state: OxalisState) => state.activeUser);
109+
const antdTheme = activeUser == null ? getTheme("auto") : getTheme(activeUser.selectedTheme);
110+
111+
return (
112+
<ConfigProvider theme={{ algorithm: antdTheme, cssVar: { key: "antd-app-theme" } }}>
113+
<App className={antdTheme === theme.darkAlgorithm ? "dark-theme" : undefined}>
114+
<Router />
115+
</App>
116+
</ConfigProvider>
117+
);
118+
}
119+
91120
document.addEventListener("DOMContentLoaded", async () => {
92121
ErrorHandling.initialize({
93122
throwAssertions: false,
@@ -110,13 +139,7 @@ document.addEventListener("DOMContentLoaded", async () => {
110139
The fix is inspired by:
111140
https://github.com/frontend-collective/react-sortable-tree/blob/9aeaf3d38b500d58e2bcc1d9b6febce12f8cc7b4/stories/barebones-no-context.js */}
112141
<DndProvider backend={HTML5Backend}>
113-
<ConfigProvider
114-
theme={{ algorithm: theme.defaultAlgorithm, cssVar: { key: "antd-app-theme" } }}
115-
>
116-
<App>
117-
<Router />
118-
</App>
119-
</ConfigProvider>
142+
<GlobalThemeProvider />
120143
</DndProvider>
121144
</QueryClientProvider>
122145
</Provider>

frontend/javascripts/navbar.tsx

+6-40
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import Request from "libs/request";
4343
import type { OxalisState } from "oxalis/store";
4444
import Store from "oxalis/store";
4545
import * as Utils from "libs/utils";
46-
import window, { document, location } from "libs/window";
46+
import window, { location } from "libs/window";
4747
import features from "features";
4848
import { setThemeAction } from "oxalis/model/actions/ui_actions";
4949
import { HelpModal } from "oxalis/view/help_modal";
@@ -503,46 +503,12 @@ function LoggedInAvatar({
503503
? activeOrganization.displayName || activeOrganization.name
504504
: organizationName;
505505

506-
const setSelectedTheme = async (theme: APIUserTheme) => {
507-
let newTheme = theme;
508-
509-
if (newTheme === "auto") {
510-
newTheme =
511-
// @ts-ignore
512-
window.matchMedia("(prefers-color-scheme: dark)").media !== "not all" &&
513-
// @ts-ignore
514-
window.matchMedia("(prefers-color-scheme: dark)").matches
515-
? "dark"
516-
: "light";
517-
}
518-
519-
const styleEl = document.getElementById("primary-stylesheet") as HTMLLinkElement;
520-
const oldThemeMatch = styleEl.href.match(/[a-z]+\.css/);
521-
const oldTheme = oldThemeMatch != null ? oldThemeMatch[0] : null;
522-
523-
if (oldTheme !== newTheme) {
524-
const newStyleEl = styleEl.cloneNode();
525-
const parentEl = styleEl.parentNode;
526-
527-
if (parentEl != null) {
528-
// @ts-expect-error ts-migrate(2339) FIXME: Property 'href' does not exist on type 'Node'.
529-
newStyleEl.href = newStyleEl.href.replace(/[a-z]+\.css/, `${newTheme}.css`);
530-
newStyleEl.addEventListener(
531-
"load",
532-
() => {
533-
parentEl.removeChild(styleEl);
534-
},
535-
{
536-
once: true,
537-
},
538-
);
539-
parentEl.insertBefore(newStyleEl, styleEl);
540-
Store.dispatch(setThemeAction(newTheme));
541-
}
542-
}
506+
const setSelectedTheme = async (newTheme: APIUserTheme) => {
507+
if (newTheme === "auto") newTheme = Utils.getSystemColorTheme();
543508

544-
if (selectedTheme !== theme) {
545-
const newUser = await updateSelectedThemeOfUser(activeUser.id, theme);
509+
if (selectedTheme !== newTheme) {
510+
const newUser = await updateSelectedThemeOfUser(activeUser.id, newTheme);
511+
Store.dispatch(setThemeAction(newTheme));
546512
Store.dispatch(setActiveUserAction(newUser));
547513
}
548514
};

frontend/javascripts/oxalis/default_state.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import type { OxalisState } from "oxalis/store";
22
import { defaultDatasetViewConfigurationWithoutNull } from "types/schemas/dataset_view_configuration.schema";
3-
import { document } from "libs/window";
43
import Constants, {
54
ControlModeEnum,
65
OrthoViews,
@@ -11,6 +10,8 @@ import Constants, {
1110
} from "oxalis/constants";
1211
import { APIAllowedMode, APIAnnotationType, APIAnnotationVisibility } from "types/api_flow_types";
1312
import constants from "oxalis/constants";
13+
import { getSystemColorTheme } from "libs/utils";
14+
1415
const defaultViewportRect = {
1516
top: 0,
1617
left: 0,
@@ -44,9 +45,6 @@ const initialAnnotationInfo = {
4445
meshes: [],
4546
};
4647

47-
const primaryStylesheetElement: HTMLLinkElement | null | undefined = document.getElementById(
48-
"primary-stylesheet",
49-
) as HTMLLinkElement;
5048
const defaultState: OxalisState = {
5149
datasetConfiguration: defaultDatasetViewConfigurationWithoutNull,
5250
userConfiguration: {
@@ -241,7 +239,7 @@ const defaultState: OxalisState = {
241239
right: false,
242240
left: false,
243241
},
244-
theme: primaryStylesheetElement?.href.includes("dark.css") ? "dark" : "light",
242+
theme: getSystemColorTheme(),
245243
busyBlockingInfo: {
246244
isBusy: false,
247245
},

frontend/javascripts/oxalis/model/helpers/listener_helpers.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { OxalisState } from "oxalis/store";
22
import Store from "oxalis/store";
3+
34
// Allows to listen on a certain property of the store.
45
// This function should only be used when listening to the Store
56
// via react components (+ redux) is not an option.

frontend/javascripts/style_dark.ts

-1
This file was deleted.

frontend/javascripts/style_light.ts

-1
This file was deleted.

frontend/javascripts/theme.tsx

-29
This file was deleted.

frontend/stylesheets/_variables.less

+6-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
--color-yz-viewport: #5660ff;
99
--color-xz-viewport: var(--color-blue-zircon);
1010
--navbar-height: 48px;
11-
--background-blue-neurons: url(/assets/images/background_neurons_drawn.svg) 0 / cover no-repeat, var(--ant-color-primary);
11+
}
12+
13+
.ant-app {
14+
// attach these variables to the antd <App> component otherwise these `--ant` variables are not in scope yet
15+
// the <App> component is expect to be there only one and very high level in the DOM tree
1216
--background-blue-organelles: url(/assets/images/background_mixed_cells_drawn.svg) 0 / cover no-repeat, var(--ant-color-primary);
17+
--background-blue-neurons: url(/assets/images/background_neurons_drawn.svg) 0 / cover no-repeat, var(--ant-color-primary);
1318
}

0 commit comments

Comments
 (0)