Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit18bffe8

Browse files
authored
impl: ability to application name as main page title (#220)
Netflix would like the ability to use application name displayed in thedashboard as the main page title instead of the URL.This PR adds a new option `useAppNameAsTitle` that allows users tospecify whether or not they want to use the application name visible inthe dashboard as Tbx main tile instead of the URL. The default willremain the URL.Unlike previous settings added for Netflix this one is also configurablefrom the UI (Coder Settings page) so not only via settings.json file.This is an option that probably makes sense for more users.
1 parent186630f commit18bffe8

File tree

11 files changed

+94
-8
lines changed

11 files changed

+94
-8
lines changed

‎CHANGELOG.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
##Unreleased
44

5+
###Added
6+
7+
- application name can now be displayed as the main title page instead of the URL
8+
59
##0.7.2 - 2025-11-03
610

711
###Changed

‎src/main/kotlin/com/coder/toolbox/CoderRemoteProvider.kt‎

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,25 @@ class CoderRemoteProvider(
5757

5858
privateval triggerSshConfig=Channel<Boolean>(Channel.CONFLATED)
5959
privateval triggerProviderVisible=Channel<Boolean>(Channel.CONFLATED)
60-
privateval settingsPage:CoderSettingsPage=CoderSettingsPage(context, triggerSshConfig)
6160
privateval dialogUi=DialogUi(context)
6261

6362
// The REST client, if we are signed in
6463
privatevar client:CoderRestClient?=null
6564

6665
// On the first load, automatically log in if we can.
6766
privatevar firstRun=true
67+
6868
privateval isInitialized:MutableStateFlow<Boolean>=MutableStateFlow(false)
6969
privateval coderHeaderPage=NewEnvironmentPage(context.i18n.pnotr(context.deploymentUrl.toString()))
70+
privateval settingsPage:CoderSettingsPage=CoderSettingsPage(context, triggerSshConfig) {
71+
client?.let { restClient->
72+
if (context.settingsStore.useAppNameAsTitle) {
73+
coderHeaderPage.setTitle(context.i18n.pnotr(restClient.appName))
74+
}else {
75+
coderHeaderPage.setTitle(context.i18n.pnotr(restClient.url.toString()))
76+
}
77+
}
78+
}
7079
privateval visibilityState=MutableStateFlow(
7180
ProviderVisibilityState(
7281
applicationVisible=false,
@@ -227,7 +236,7 @@ class CoderRemoteProvider(
227236
val url= context.settingsStore.workspaceCreateUrl?: client?.url?.withPath("/templates").toString()
228237
context.desktop.browse(
229238
url
230-
.replace("\$workspaceOwner", client?.me()?.username?:"")
239+
.replace("\$workspaceOwner", client?.me?.username?:"")
231240
) {
232241
context.ui.showErrorInfoPopup(it)
233242
}
@@ -333,8 +342,11 @@ class CoderRemoteProvider(
333342
}
334343
context.logger.info("Starting initialization with the new settings")
335344
this@CoderRemoteProvider.client= restClient
336-
coderHeaderPage.setTitle(context.i18n.pnotr(restClient.url.toString()))
337-
345+
if (context.settingsStore.useAppNameAsTitle) {
346+
coderHeaderPage.setTitle(context.i18n.pnotr(restClient.appName))
347+
}else {
348+
coderHeaderPage.setTitle(context.i18n.pnotr(restClient.url.toString()))
349+
}
338350
environments.showLoadingMessage()
339351
pollJob= poll(restClient, cli)
340352
context.logger.info("Workspace poll job with name${pollJob.toString()} was created while handling URI$uri")
@@ -421,7 +433,11 @@ class CoderRemoteProvider(
421433
context.logger.info("Cancelled workspace poll job${pollJob.toString()} in order to start a new one")
422434
}
423435
environments.showLoadingMessage()
424-
coderHeaderPage.setTitle(context.i18n.pnotr(client.url.toString()))
436+
if (context.settingsStore.useAppNameAsTitle) {
437+
coderHeaderPage.setTitle(context.i18n.pnotr(client.appName))
438+
}else {
439+
coderHeaderPage.setTitle(context.i18n.pnotr(client.url.toString()))
440+
}
425441
context.logger.info("Displaying${client.url} in the UI")
426442
pollJob= poll(client, cli)
427443
context.logger.info("Workspace poll job with name${pollJob.toString()} was created")

‎src/main/kotlin/com/coder/toolbox/sdk/CoderRestClient.kt‎

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import com.coder.toolbox.sdk.ex.APIResponseException
1010
importcom.coder.toolbox.sdk.interceptors.Interceptors
1111
importcom.coder.toolbox.sdk.v2.CoderV2RestFacade
1212
importcom.coder.toolbox.sdk.v2.models.ApiErrorResponse
13+
importcom.coder.toolbox.sdk.v2.models.Appearance
1314
importcom.coder.toolbox.sdk.v2.models.BuildInfo
1415
importcom.coder.toolbox.sdk.v2.models.CreateWorkspaceBuildRequest
1516
importcom.coder.toolbox.sdk.v2.models.Template
@@ -45,6 +46,7 @@ open class CoderRestClient(
4546

4647
lateinitvar me:User
4748
lateinitvar buildVersion:String
49+
lateinitvar appName:String
4850

4951
init {
5052
setupSession()
@@ -94,14 +96,15 @@ open class CoderRestClient(
9496
suspendfuninitializeSession():User {
9597
me= me()
9698
buildVersion= buildInfo().version
99+
appName= appearance().applicationName
97100
return me
98101
}
99102

100103
/**
101104
* Retrieve the current user.
102105
* @throws [APIResponseException].
103106
*/
104-
suspendfunme():User {
107+
internalsuspendfunme():User {
105108
val userResponse= retroRestClient.me()
106109
if (!userResponse.isSuccessful) {
107110
throwAPIResponseException(
@@ -117,6 +120,25 @@ open class CoderRestClient(
117120
}
118121
}
119122

123+
/**
124+
* Retrieves the visual dashboard configuration.
125+
*/
126+
internalsuspendfunappearance():Appearance {
127+
val appearanceResponse= retroRestClient.appearance()
128+
if (!appearanceResponse.isSuccessful) {
129+
throwAPIResponseException(
130+
"initializeSession",
131+
url,
132+
appearanceResponse.code(),
133+
appearanceResponse.parseErrorBody(moshi)
134+
)
135+
}
136+
137+
return requireNotNull(appearanceResponse.body()) {
138+
"Successful response returned null body for visual dashboard configuration"
139+
}
140+
}
141+
120142
/**
121143
* Retrieves the available workspaces created by the user.
122144
* @throws [APIResponseException].

‎src/main/kotlin/com/coder/toolbox/sdk/v2/CoderV2RestFacade.kt‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
packagecom.coder.toolbox.sdk.v2
22

3+
importcom.coder.toolbox.sdk.v2.models.Appearance
34
importcom.coder.toolbox.sdk.v2.models.BuildInfo
45
importcom.coder.toolbox.sdk.v2.models.CreateWorkspaceBuildRequest
56
importcom.coder.toolbox.sdk.v2.models.Template
@@ -23,6 +24,12 @@ interface CoderV2RestFacade {
2324
@GET("api/v2/users/me")
2425
suspendfunme():Response<User>
2526

27+
/**
28+
* Returns the configuration of the visual dashboard.
29+
*/
30+
@GET("api/v2/appearance")
31+
suspendfunappearance():Response<Appearance>
32+
2633
/**
2734
* Retrieves all workspaces the authenticated user has access to.
2835
*/
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
packagecom.coder.toolbox.sdk.v2.models
2+
3+
importcom.squareup.moshi.Json
4+
importcom.squareup.moshi.JsonClass
5+
6+
@JsonClass(generateAdapter=true)
7+
data classAppearance(
8+
@property:Json(name = "application_name")valapplicationName:String
9+
)

‎src/main/kotlin/com/coder/toolbox/settings/ReadOnlyCoderSettings.kt‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ interface ReadOnlyCoderSettings {
1919
*/
2020
val defaultURL:String
2121

22+
/**
23+
* Whether to display the application name instead of the URL
24+
* in the main screen. Defaults to URL
25+
*/
26+
val useAppNameAsTitle:Boolean
27+
2228
/**
2329
* Used to download the Coder CLI which is necessary to proxy SSH
2430
* connections. The If-None-Match header will be set to the SHA1 of the CLI

‎src/main/kotlin/com/coder/toolbox/store/CoderSettingsStore.kt‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class CoderSettingsStore(
3838
// Properties implementation
3939
overrideval lastDeploymentURL:String? get()= store[LAST_USED_URL]
4040
overrideval defaultURL:String get()= store[DEFAULT_URL]?:"https://dev.coder.com"
41+
overrideval useAppNameAsTitle:Boolean get()= store[APP_NAME_AS_TITLE]?.toBooleanStrictOrNull()?:false
4142
overrideval binarySource:String? get()= store[BINARY_SOURCE]
4243
overrideval binaryDirectory:String? get()= store[BINARY_DIRECTORY]
4344
overrideval disableSignatureVerification:Boolean
@@ -165,6 +166,10 @@ class CoderSettingsStore(
165166
store[LAST_USED_URL]= url.toString()
166167
}
167168

169+
funupdateUseAppNameAsTitle(appNameAsTitle:Boolean) {
170+
store[APP_NAME_AS_TITLE]= appNameAsTitle.toString()
171+
}
172+
168173
funupdateBinarySource(source:String) {
169174
store[BINARY_SOURCE]= source
170175
}

‎src/main/kotlin/com/coder/toolbox/store/StoreKeys.kt‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ internal const val LAST_USED_URL = "lastDeploymentURL"
66

77
internalconstvalDEFAULT_URL="defaultURL"
88

9+
internalconstvalAPP_NAME_AS_TITLE="useAppNameAsTitle"
10+
911
internalconstvalBINARY_SOURCE="binarySource"
1012

1113
internalconstvalBINARY_DIRECTORY="binaryDirectory"

‎src/main/kotlin/com/coder/toolbox/views/CoderSettingsPage.kt‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ import kotlinx.coroutines.launch
2828
* TODO@JB: There is no scroll, and our settings do not fit. As a consequence,
2929
* I have not been able to test this page.
3030
*/
31-
classCoderSettingsPage(privatevalcontext:CoderToolboxContext,triggerSshConfig:Channel<Boolean>) :
31+
classCoderSettingsPage(
32+
privatevalcontext:CoderToolboxContext,
33+
triggerSshConfig:Channel<Boolean>,
34+
privatevalonSettingsClosed: ()->Unit
35+
) :
3236
CoderPage(MutableStateFlow(context.i18n.ptrl("Coder Settings")),false) {
3337
privateval settings= context.settingsStore.readOnly()
3438

@@ -41,6 +45,8 @@ class CoderSettingsPage(private val context: CoderToolboxContext, triggerSshConf
4145
TextField(context.i18n.ptrl("Data directory"), settings.dataDirectory?:"",TextType.General)
4246
privateval enableDownloadsField=
4347
CheckboxField(settings.enableDownloads, context.i18n.ptrl("Enable downloads"))
48+
privateval useAppNameField=
49+
CheckboxField(settings.useAppNameAsTitle, context.i18n.ptrl("Use app name as main page title instead of URL"))
4450

4551
privateval disableSignatureVerificationField=CheckboxField(
4652
settings.disableSignatureVerification,
@@ -95,6 +101,7 @@ class CoderSettingsPage(private val context: CoderToolboxContext, triggerSshConf
95101
listOf(
96102
binarySourceField,
97103
enableDownloadsField,
104+
useAppNameField,
98105
binaryDirectoryField,
99106
enableBinaryDirectoryFallbackField,
100107
disableSignatureVerificationField,
@@ -121,6 +128,7 @@ class CoderSettingsPage(private val context: CoderToolboxContext, triggerSshConf
121128
context.settingsStore.updateBinaryDirectory(binaryDirectoryField.contentState.value)
122129
context.settingsStore.updateDataDirectory(dataDirectoryField.contentState.value)
123130
context.settingsStore.updateEnableDownloads(enableDownloadsField.checkedState.value)
131+
context.settingsStore.updateUseAppNameAsTitle(useAppNameField.checkedState.value)
124132
context.settingsStore.updateDisableSignatureVerification(disableSignatureVerificationField.checkedState.value)
125133
context.settingsStore.updateSignatureFallbackStrategy(signatureFallbackStrategyField.checkedState.value)
126134
context.settingsStore.updateHttpClientLogLevel(httpLoggingField.selectedValueState.value)
@@ -164,6 +172,9 @@ class CoderSettingsPage(private val context: CoderToolboxContext, triggerSshConf
164172
enableDownloadsField.checkedState.update {
165173
settings.enableDownloads
166174
}
175+
useAppNameField.checkedState.update {
176+
settings.useAppNameAsTitle
177+
}
167178
signatureFallbackStrategyField.checkedState.update {
168179
settings.fallbackOnCoderForSignatures.isAllowed()
169180
}
@@ -225,5 +236,6 @@ class CoderSettingsPage(private val context: CoderToolboxContext, triggerSshConf
225236

226237
overridefunafterHide() {
227238
visibilityUpdateJob.cancel()
239+
onSettingsClosed()
228240
}
229241
}

‎src/main/resources/localization/defaultMessages.po‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,3 +189,6 @@ msgstr ""
189189

190190
msgid"Workspace name"
191191
msgstr""
192+
193+
msgid"Use app name as main page title instead of URL"
194+
msgstr""

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp