From 546fd8aedb77657ecda4b902aa860d70a4fb7055 Mon Sep 17 00:00:00 2001 From: dev-warrior777 <> Date: Sun, 24 Nov 2024 18:44:22 +0800 Subject: [PATCH 1/8] client,webserver: Use the app build version as Version in UI. - Use the value from client/app/version.go - Place at the foot of Settings dialog - Re-purpose 'BUILD ID' as "Version for translations and find relevant translations --- client/app/config.go | 2 ++ client/cmd/bisonw/config.go | 1 + client/cmd/bisonw/main.go | 2 +- client/webserver/http.go | 2 ++ client/webserver/locales/de-de.go | 2 +- client/webserver/locales/en-us.go | 2 +- client/webserver/locales/pl-pl.go | 2 +- client/webserver/locales/pt-br.go | 2 +- client/webserver/locales/zh-cn.go | 2 +- .../webserver/site/src/html/bodybuilder.tmpl | 4 +-- client/webserver/site/src/html/settings.tmpl | 3 +- client/webserver/site/src/js/app.ts | 10 +++--- client/webserver/site/src/js/locales.ts | 9 ++++-- client/webserver/site/src/js/registry.ts | 2 +- client/webserver/site/src/js/settings.ts | 11 ++++--- client/webserver/site/webpack/common.js | 14 ++++---- client/webserver/template.go | 32 +++++++++---------- client/webserver/webserver.go | 4 ++- 18 files changed, 60 insertions(+), 46 deletions(-) diff --git a/client/app/config.go b/client/app/config.go index f2aadbc687..36e145b049 100644 --- a/client/app/config.go +++ b/client/app/config.go @@ -143,6 +143,7 @@ type Config struct { WebConfig LogConfig MMConfig + AppVersion string // AppData and ConfigPath should be parsed from the command-line, // as it makes no sense to set these in the config file itself. If no values // are assigned, defaults will be used. @@ -348,6 +349,7 @@ func ResolveConfig(appData string, cfg *Config) error { if cfg.MMConfig.EventLogDBPath == "" { cfg.MMConfig.EventLogDBPath = defaultMMEventLogDBPath } + return nil } diff --git a/client/cmd/bisonw/config.go b/client/cmd/bisonw/config.go index e102adf12e..467c16b264 100644 --- a/client/cmd/bisonw/config.go +++ b/client/cmd/bisonw/config.go @@ -13,6 +13,7 @@ func configure() (*app.Config, error) { // or the version flag was specified. Override any environment variables // with parsed command line flags. iniCfg := app.DefaultConfig + iniCfg.AppVersion = app.Version preCfg := iniCfg if err := app.ParseCLIConfig(&preCfg); err != nil { return nil, err diff --git a/client/cmd/bisonw/main.go b/client/cmd/bisonw/main.go index 01e7c94065..eb11e5c0d6 100644 --- a/client/cmd/bisonw/main.go +++ b/client/cmd/bisonw/main.go @@ -154,7 +154,7 @@ func runCore(cfg *app.Config) error { } if !cfg.NoWeb { - webSrv, err := webserver.New(cfg.Web(clientCore, marketMaker, logMaker.Logger("WEB"), utc)) + webSrv, err := webserver.New(cfg.Web(clientCore, marketMaker, logMaker.Logger("WEB"), utc), cfg.AppVersion) if err != nil { return fmt.Errorf("failed creating web server: %w", err) } diff --git a/client/webserver/http.go b/client/webserver/http.go index 45ca372e66..56f533fed0 100644 --- a/client/webserver/http.go +++ b/client/webserver/http.go @@ -260,6 +260,7 @@ func (s *WebServer) handleSettings(w http.ResponseWriter, r *http.Request) { FiatCurrency string Exchanges map[string]*core.Exchange IsInitialized bool + AppVersion string }{ CommonArguments: *common, KnownExchanges: s.knownUnregisteredExchanges(xcs), @@ -267,6 +268,7 @@ func (s *WebServer) handleSettings(w http.ResponseWriter, r *http.Request) { FiatRateSources: s.core.FiatRateSources(), Exchanges: xcs, IsInitialized: s.core.IsInitialized(), + AppVersion: s.appVersion, } s.sendTemplate(w, "settings", data) } diff --git a/client/webserver/locales/de-de.go b/client/webserver/locales/de-de.go index ecd2becfea..497f316522 100644 --- a/client/webserver/locales/de-de.go +++ b/client/webserver/locales/de-de.go @@ -135,7 +135,7 @@ var DeDE = map[string]*intl.Translation{ "Export Account": {T: "Account exportieren"}, "simultaneous_servers_msg": {T: "Der unterstützt die gleichzeitige Nutzung einer beliebigen Anzahl von DEX-Servern."}, "Change App Password": {T: "App-Passwort ändern"}, - "Build ID": {T: "Build ID"}, + "Build ID": {T: "Version"}, "Connect": {T: "Verbinden"}, "Send": {T: "Senden"}, "Deposit": {T: "Einzahlen"}, diff --git a/client/webserver/locales/en-us.go b/client/webserver/locales/en-us.go index 8d15eef0cc..2f8daa2291 100644 --- a/client/webserver/locales/en-us.go +++ b/client/webserver/locales/en-us.go @@ -167,7 +167,7 @@ var EnUS = map[string]*intl.Translation{ "browser_ntfn_blocked": {T: "Browser notifications are currently blocked. Please unblock this site in your browser to receive notifications."}, "enable_browser_ntfn_info": {T: "Desktop notifications appear even when this window is not active. When you have other applications open this can be helpful as you will be notified on DCRDEX events. Customize below the types of notifications you would like to receive."}, "Save Notifications": {T: "Save Notifications"}, - "Build ID": {T: "Build ID"}, + "Build ID": {T: "Version"}, "Connect": {T: "Connect"}, "Send": {T: "Send"}, "Deposit": {T: "Deposit"}, // unused diff --git a/client/webserver/locales/pl-pl.go b/client/webserver/locales/pl-pl.go index c1f7be9a99..d47cf94cb6 100644 --- a/client/webserver/locales/pl-pl.go +++ b/client/webserver/locales/pl-pl.go @@ -133,7 +133,7 @@ var PlPL = map[string]*intl.Translation{ "Export Account": {T: "Eksportuj konto"}, "simultaneous_servers_msg": {T: "Klient Decred DEX wspiera jednoczesne korzystanie z wielu serwerów DEX."}, "Change App Password": {T: "Zmień hasło aplikacji"}, - "Build ID": {T: "ID builda"}, + "Build ID": {T: "Wersja"}, "Connect": {T: "Połącz"}, "Withdraw": {T: "Wypłać"}, "Deposit": {T: "Zdeponuj"}, diff --git a/client/webserver/locales/pt-br.go b/client/webserver/locales/pt-br.go index 38187ed0b2..db2ccbcc89 100644 --- a/client/webserver/locales/pt-br.go +++ b/client/webserver/locales/pt-br.go @@ -133,7 +133,7 @@ var PtBr = map[string]*intl.Translation{ "Export Account": {T: "Exportar Conta"}, "simultaneous_servers_msg": {T: "O cliente da DEX suporta simultâneos números de servidores DEX."}, "Change App Password": {T: "Trocar Senha do aplicativo"}, - "Build ID": {T: "ID da Build"}, + "Build ID": {T: "Versão"}, "Connect": {T: "Conectar"}, "Withdraw": {T: "Retirar"}, "Deposit": {T: "Depositar"}, diff --git a/client/webserver/locales/zh-cn.go b/client/webserver/locales/zh-cn.go index 0b68f012b7..4adc2fe42d 100644 --- a/client/webserver/locales/zh-cn.go +++ b/client/webserver/locales/zh-cn.go @@ -135,7 +135,7 @@ var ZhCN = map[string]*intl.Translation{ "Export Account": {T: "退出账户"}, "simultaneous_servers_msg": {T: "Decred DEX 客户端支持同时使用任意数量的 DEX 服务器。"}, "Change App Password": {T: "更改应用程序密码"}, - "Build ID": {T: "构建 ID"}, + "Build ID": {T: "版本"}, "Connect": {T: "连接"}, "Send": {T: "发送"}, "Deposit": {T: "存款"}, diff --git a/client/webserver/site/src/html/bodybuilder.tmpl b/client/webserver/site/src/html/bodybuilder.tmpl index fb0fca5e3d..2bd698057a 100644 --- a/client/webserver/site/src/html/bodybuilder.tmpl +++ b/client/webserver/site/src/html/bodybuilder.tmpl @@ -9,7 +9,7 @@ {{.Title}} - + - + {{end}} diff --git a/client/webserver/site/src/html/settings.tmpl b/client/webserver/site/src/html/settings.tmpl index e99927a64b..2c4b75f61e 100644 --- a/client/webserver/site/src/html/settings.tmpl +++ b/client/webserver/site/src/html/settings.tmpl @@ -79,7 +79,8 @@ -

[[[Build ID]]]:

+ {{$version := .AppVersion}} +

[[[Build ID]]]: {{$version}}

diff --git a/client/webserver/site/src/js/app.ts b/client/webserver/site/src/js/app.ts index aa035b90f0..1908cadc9a 100644 --- a/client/webserver/site/src/js/app.ts +++ b/client/webserver/site/src/js/app.ts @@ -161,7 +161,7 @@ export default class Application { authed: boolean user: User seedGenTime: number - commitHash: string + // commitHash: string // TODO: Remove showPopups: boolean loggers: Record recorders: Record @@ -185,14 +185,15 @@ export default class Application { this.notes = [] this.pokes = [] this.seedGenTime = 0 - this.commitHash = process.env.COMMITHASH || '' + // this.commitHash = process.env.COMMITHASH || '' // TODO: Remove this.noteReceivers = [] this.fiatRatesMap = {} this.showPopups = State.fetchLocal(State.popupsLK) === '1' this.txHistoryMap = {} this.requiredActions = {} - console.log('Bison Wallet, Build', this.commitHash.substring(0, 7)) + console.log('Bison Wallet') + // console.log('Bison Wallet, Build', this.commitHash.substring(0, 7)) // TODO: Remove // Set Bootstrap dark theme attribute if dark mode is enabled. if (State.isDark()) { @@ -261,7 +262,8 @@ export default class Application { // Don't fetch the user until we know what page we're on. await this.fetchUser() const ignoreCachedLocale = process.env.NODE_ENV === 'development' - await intl.loadLocale(this.lang, this.commitHash, ignoreCachedLocale) + await intl.loadLocale(this.lang, ignoreCachedLocale) + // await intl.loadLocale(this.lang, this.commitHash, ignoreCachedLocale) // TODO: Remove // The application is free to respond with a page that differs from the // one requested in the omnibox, e.g. routing though a login page. Set the // current URL state based on the actual page. diff --git a/client/webserver/site/src/js/locales.ts b/client/webserver/site/src/js/locales.ts index ff7b927234..eb66c0ec86 100644 --- a/client/webserver/site/src/js/locales.ts +++ b/client/webserver/site/src/js/locales.ts @@ -222,16 +222,19 @@ export const ID_DELETE_BOT = 'DELETE_BOT' let locale: Locale -export async function loadLocale (lang: string, commitHash: string, skipCache: boolean) { +export async function loadLocale (lang: string, /* commitHash: string, TODO: Remove */ skipCache: boolean) { if (!skipCache) { const specs = State.fetchLocal(State.localeSpecsKey) - if (specs && specs.lang === lang && specs.commitHash === commitHash) { + if (specs && specs.lang === lang) { + // if (specs && specs.lang === lang && specs.commitHash === commitHash) { // TODO: Remove locale = State.fetchLocal(State.localeKey) return } } locale = await postJSON('/api/locale', lang) - State.storeLocal(State.localeSpecsKey, { lang, commitHash }) + // TODO: Remove + Change + State.storeLocal(State.localeSpecsKey, { lang }) + // State.storeLocal(State.localeSpecsKey, { lang, commitHash }) State.storeLocal(State.localeKey, locale) } diff --git a/client/webserver/site/src/js/registry.ts b/client/webserver/site/src/js/registry.ts index d4832abee4..fe9639ad01 100644 --- a/client/webserver/site/src/js/registry.ts +++ b/client/webserver/site/src/js/registry.ts @@ -1275,7 +1275,7 @@ export interface Application { exchanges: Record fiatRatesMap: Record showPopups: boolean - commitHash: string + // commitHash: string // TODO: Remove authed: boolean start (): Promise reconnected (): void diff --git a/client/webserver/site/src/js/settings.ts b/client/webserver/site/src/js/settings.ts index 5f973de5de..5ce7f40e88 100644 --- a/client/webserver/site/src/js/settings.ts +++ b/client/webserver/site/src/js/settings.ts @@ -61,11 +61,12 @@ export default class SettingsPage extends BasePage { app().showPopups = show }) - page.commitHash.textContent = app().commitHash.substring(0, 7) - Doc.bind(page.addADex, 'click', () => { - this.dexAddrForm.refresh() - this.showForm(page.dexAddrForm) - }) + // TODO: Remove + // page.commitHash.textContent = app().commitHash.substring(0, 7) + // Doc.bind(page.addADex, 'click', () => { + // this.dexAddrForm.refresh() + // this.showForm(page.dexAddrForm) + // }) this.fiatRateSources.forEach(src => { Doc.bind(src, 'change', async () => { diff --git a/client/webserver/site/webpack/common.js b/client/webserver/site/webpack/common.js index 985000c145..02f52e9cc8 100644 --- a/client/webserver/site/webpack/common.js +++ b/client/webserver/site/webpack/common.js @@ -6,9 +6,10 @@ const StyleLintPlugin = require('stylelint-webpack-plugin') const ESLintPlugin = require('eslint-webpack-plugin') const child_process = require('child_process') -function git(command) { - return child_process.execSync(`git ${command}`, { encoding: 'utf8' }).trim(); -} +// TODO: Remove +// function git(command) { +// return child_process.execSync(`git ${command}`, { encoding: 'utf8' }).trim(); +// } module.exports = { target: "web", @@ -38,9 +39,10 @@ module.exports = { ] }, plugins: [ - new webpack.EnvironmentPlugin({ - COMMITHASH: git('rev-parse HEAD'), - }), + // TODO: Remove + // new webpack.EnvironmentPlugin({ + // COMMITHASH: git('rev-parse HEAD'), + // }), new CleanWebpackPlugin(), new MiniCssExtractPlugin({ filename: '../dist/style.css' diff --git a/client/webserver/template.go b/client/webserver/template.go index 0dba710eed..f0939675a6 100644 --- a/client/webserver/template.go +++ b/client/webserver/template.go @@ -5,18 +5,14 @@ package webserver import ( "bytes" - "encoding/hex" "fmt" "html/template" "io/fs" "os" "strings" - "runtime/debug" - "decred.org/dcrdex/client/intl" "decred.org/dcrdex/client/webserver/locales" - "decred.org/dcrdex/dex/encode" "golang.org/x/text/cases" "golang.org/x/text/language" ) @@ -188,17 +184,18 @@ func (t *templates) exec(name string, data any) (string, error) { return page.String(), err } -var commit = func() string { - if info, ok := debug.ReadBuildInfo(); ok { - for _, setting := range info.Settings { - if setting.Key == "vcs.revision" && len(setting.Value) >= 8 { - return setting.Value - } - } - } +// TODO: Remove +// var commit = func() string { +// if info, ok := debug.ReadBuildInfo(); ok { +// for _, setting := range info.Settings { +// if setting.Key == "vcs.revision" && len(setting.Value) >= 8 { +// return setting.Value +// } +// } +// } - return hex.EncodeToString(encode.RandomBytes(4)) -}() +// return hex.EncodeToString(encode.RandomBytes(4)) +// }() // templateFuncs are able to be called during template execution. var templateFuncs = template.FuncMap{ @@ -228,7 +225,8 @@ var templateFuncs = template.FuncMap{ } return parts[0] }, - "commitHash": func() string { - return commit[:8] - }, + // TODO: Remove + // "commitHash": func() string { + // return commit[:8] + // }, } diff --git a/client/webserver/webserver.go b/client/webserver/webserver.go index 1ea09fa6fe..9b2ab7a4ad 100644 --- a/client/webserver/webserver.go +++ b/client/webserver/webserver.go @@ -271,12 +271,13 @@ type WebServer struct { bondBuf map[uint32]valStamp useDEXBranding bool + appVersion string } // New is the constructor for a new WebServer. CustomSiteDir in the Config can // be left blank, in which case a handful of default locations will be checked. // This will work in most cases. -func New(cfg *Config) (*WebServer, error) { +func New(cfg *Config, appVersion string) (*WebServer, error) { log = cfg.Logger // Only look for files on disk if NoEmbed is set. This is necessary since @@ -392,6 +393,7 @@ func New(cfg *Config) (*WebServer, error) { cachedPasswords: make(map[string]*cachedPassword), bondBuf: map[uint32]valStamp{}, useDEXBranding: useDEXBranding, + appVersion: appVersion, } s.lang.Store(lang) From b8e9c90f65bca81f447ac685a3f21123e496caa5 Mon Sep 17 00:00:00 2001 From: dev-warrior777 <> Date: Mon, 25 Nov 2024 00:27:31 +0800 Subject: [PATCH 2/8] client,webserver-tests: Fix tests --- client/webserver/live_test.go | 3 ++- client/webserver/webserver_test.go | 9 ++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/client/webserver/live_test.go b/client/webserver/live_test.go index cae2faf0c1..85ba7b0b75 100644 --- a/client/webserver/live_test.go +++ b/client/webserver/live_test.go @@ -2692,6 +2692,7 @@ func TestServer(t *testing.T) { tCore.PostBond(&core.PostBondForm{Addr: firstDEX, Bond: 1, Asset: &assetID}) } + var appVersion = "1.0.2+release.local" s, err := New(&Config{ Core: tCore, MarketMaker: &TMarketMaker{ @@ -2703,7 +2704,7 @@ func TestServer(t *testing.T) { Logger: logger, NoEmbed: true, // use files on disk, and reload on each page load HttpProf: true, - }) + }, appVersion) if err != nil { t.Fatalf("error creating server: %v", err) } diff --git a/client/webserver/webserver_test.go b/client/webserver/webserver_test.go index 40cbf0d52c..5a24943f2b 100644 --- a/client/webserver/webserver_test.go +++ b/client/webserver/webserver_test.go @@ -391,12 +391,13 @@ func newTServer(t *testing.T, start bool) (*WebServer, *TCore, func()) { t.Helper() c := &TCore{} var shutdown func() + var appVersion = "1.0.2+release.local" ctx, killCtx := context.WithCancel(tCtx) s, err := New(&Config{ Core: c, Addr: "127.0.0.1:0", Logger: tLogger, - }) + }, appVersion) if err != nil { t.Fatalf("error creating server: %v", err) } @@ -473,13 +474,14 @@ func TestNew_siteError(t *testing.T) { t.Fatalf("Cannot cd to %q", dir) } + var appVersion = "1.0.2+release.local" c := &TCore{} _, err = New(&Config{ Core: c, Addr: "127.0.0.1:0", Logger: tLogger, NoEmbed: true, // this tests locating on-disk files, not the embedded ones - }) + }, appVersion) if err == nil || !strings.HasPrefix(err.Error(), "no HTML template files found") { t.Errorf("Should have failed to start with no site folder.") } @@ -495,11 +497,12 @@ func TestConnectBindError(t *testing.T) { defer shutdown() tAddr := s0.addr + var appVersion = "1.0.2+release.local" s, err := New(&Config{ Core: &TCore{}, Addr: tAddr, Logger: tLogger, - }) + }, appVersion) if err != nil { t.Fatalf("error creating server: %v", err) } From 65ed1890193014c88985e0d1b1129d18d786cfd7 Mon Sep 17 00:00:00 2001 From: dev-warrior777 <> Date: Tue, 26 Nov 2024 16:06:55 +0800 Subject: [PATCH 3/8] bisonw-desktop: Show app version for bisonw-desktop. --- client/cmd/bisonw-desktop/app.go | 2 +- client/cmd/bisonw-desktop/config.go | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/client/cmd/bisonw-desktop/app.go b/client/cmd/bisonw-desktop/app.go index 327525e5b3..b7e33fe2cd 100644 --- a/client/cmd/bisonw-desktop/app.go +++ b/client/cmd/bisonw-desktop/app.go @@ -222,7 +222,7 @@ func mainCore() error { }() } - webSrv, err := webserver.New(cfg.Web(clientCore, marketMaker, logMaker.Logger("WEB"), utc)) + webSrv, err := webserver.New(cfg.Web(clientCore, marketMaker, logMaker.Logger("WEB"), utc), cfg.AppVersion) if err != nil { return fmt.Errorf("failed creating web server: %w", err) } diff --git a/client/cmd/bisonw-desktop/config.go b/client/cmd/bisonw-desktop/config.go index 46f7202641..36e9eee284 100644 --- a/client/cmd/bisonw-desktop/config.go +++ b/client/cmd/bisonw-desktop/config.go @@ -49,6 +49,8 @@ func configure() (*Config, error) { return nil, err } + cfg.AppVersion = app.Version + // Resolve unset fields. return &cfg, app.ResolveConfig(appData, &cfg.Config) } From 2833bd5db9d53dbcfdeb615580098e7061a914e5 Mon Sep 17 00:00:00 2001 From: dev-warrior777 <> Date: Tue, 26 Nov 2024 18:35:12 +0800 Subject: [PATCH 4/8] client,webserver: Remove commented TODO's --- client/webserver/site/src/js/app.ts | 4 ---- client/webserver/site/src/js/locales.ts | 5 +---- client/webserver/site/src/js/registry.ts | 1 - client/webserver/site/src/js/settings.ts | 7 ------- client/webserver/site/webpack/common.js | 8 -------- client/webserver/template.go | 17 ----------------- 6 files changed, 1 insertion(+), 41 deletions(-) diff --git a/client/webserver/site/src/js/app.ts b/client/webserver/site/src/js/app.ts index 1908cadc9a..61c4140b0b 100644 --- a/client/webserver/site/src/js/app.ts +++ b/client/webserver/site/src/js/app.ts @@ -161,7 +161,6 @@ export default class Application { authed: boolean user: User seedGenTime: number - // commitHash: string // TODO: Remove showPopups: boolean loggers: Record recorders: Record @@ -185,7 +184,6 @@ export default class Application { this.notes = [] this.pokes = [] this.seedGenTime = 0 - // this.commitHash = process.env.COMMITHASH || '' // TODO: Remove this.noteReceivers = [] this.fiatRatesMap = {} this.showPopups = State.fetchLocal(State.popupsLK) === '1' @@ -193,7 +191,6 @@ export default class Application { this.requiredActions = {} console.log('Bison Wallet') - // console.log('Bison Wallet, Build', this.commitHash.substring(0, 7)) // TODO: Remove // Set Bootstrap dark theme attribute if dark mode is enabled. if (State.isDark()) { @@ -263,7 +260,6 @@ export default class Application { await this.fetchUser() const ignoreCachedLocale = process.env.NODE_ENV === 'development' await intl.loadLocale(this.lang, ignoreCachedLocale) - // await intl.loadLocale(this.lang, this.commitHash, ignoreCachedLocale) // TODO: Remove // The application is free to respond with a page that differs from the // one requested in the omnibox, e.g. routing though a login page. Set the // current URL state based on the actual page. diff --git a/client/webserver/site/src/js/locales.ts b/client/webserver/site/src/js/locales.ts index eb66c0ec86..561787eec1 100644 --- a/client/webserver/site/src/js/locales.ts +++ b/client/webserver/site/src/js/locales.ts @@ -222,19 +222,16 @@ export const ID_DELETE_BOT = 'DELETE_BOT' let locale: Locale -export async function loadLocale (lang: string, /* commitHash: string, TODO: Remove */ skipCache: boolean) { +export async function loadLocale (lang: string, skipCache: boolean) { if (!skipCache) { const specs = State.fetchLocal(State.localeSpecsKey) if (specs && specs.lang === lang) { - // if (specs && specs.lang === lang && specs.commitHash === commitHash) { // TODO: Remove locale = State.fetchLocal(State.localeKey) return } } locale = await postJSON('/api/locale', lang) - // TODO: Remove + Change State.storeLocal(State.localeSpecsKey, { lang }) - // State.storeLocal(State.localeSpecsKey, { lang, commitHash }) State.storeLocal(State.localeKey, locale) } diff --git a/client/webserver/site/src/js/registry.ts b/client/webserver/site/src/js/registry.ts index fe9639ad01..d4e9c5fcd9 100644 --- a/client/webserver/site/src/js/registry.ts +++ b/client/webserver/site/src/js/registry.ts @@ -1275,7 +1275,6 @@ export interface Application { exchanges: Record fiatRatesMap: Record showPopups: boolean - // commitHash: string // TODO: Remove authed: boolean start (): Promise reconnected (): void diff --git a/client/webserver/site/src/js/settings.ts b/client/webserver/site/src/js/settings.ts index 5ce7f40e88..7f58bb3d64 100644 --- a/client/webserver/site/src/js/settings.ts +++ b/client/webserver/site/src/js/settings.ts @@ -61,13 +61,6 @@ export default class SettingsPage extends BasePage { app().showPopups = show }) - // TODO: Remove - // page.commitHash.textContent = app().commitHash.substring(0, 7) - // Doc.bind(page.addADex, 'click', () => { - // this.dexAddrForm.refresh() - // this.showForm(page.dexAddrForm) - // }) - this.fiatRateSources.forEach(src => { Doc.bind(src, 'change', async () => { const res = await postJSON('/api/toggleratesource', { diff --git a/client/webserver/site/webpack/common.js b/client/webserver/site/webpack/common.js index 02f52e9cc8..c279913ac8 100644 --- a/client/webserver/site/webpack/common.js +++ b/client/webserver/site/webpack/common.js @@ -6,10 +6,6 @@ const StyleLintPlugin = require('stylelint-webpack-plugin') const ESLintPlugin = require('eslint-webpack-plugin') const child_process = require('child_process') -// TODO: Remove -// function git(command) { -// return child_process.execSync(`git ${command}`, { encoding: 'utf8' }).trim(); -// } module.exports = { target: "web", @@ -39,10 +35,6 @@ module.exports = { ] }, plugins: [ - // TODO: Remove - // new webpack.EnvironmentPlugin({ - // COMMITHASH: git('rev-parse HEAD'), - // }), new CleanWebpackPlugin(), new MiniCssExtractPlugin({ filename: '../dist/style.css' diff --git a/client/webserver/template.go b/client/webserver/template.go index f0939675a6..bd3eb7b50e 100644 --- a/client/webserver/template.go +++ b/client/webserver/template.go @@ -184,19 +184,6 @@ func (t *templates) exec(name string, data any) (string, error) { return page.String(), err } -// TODO: Remove -// var commit = func() string { -// if info, ok := debug.ReadBuildInfo(); ok { -// for _, setting := range info.Settings { -// if setting.Key == "vcs.revision" && len(setting.Value) >= 8 { -// return setting.Value -// } -// } -// } - -// return hex.EncodeToString(encode.RandomBytes(4)) -// }() - // templateFuncs are able to be called during template execution. var templateFuncs = template.FuncMap{ "toUpper": strings.ToUpper, @@ -225,8 +212,4 @@ var templateFuncs = template.FuncMap{ } return parts[0] }, - // TODO: Remove - // "commitHash": func() string { - // return commit[:8] - // }, } From 874fe24d8a0be9c9317e61bb05423cc7b283eba5 Mon Sep 17 00:00:00 2001 From: dev-warrior777 <> Date: Wed, 27 Nov 2024 17:22:39 +0800 Subject: [PATCH 5/8] client,webserver: Hide Settings link when user un-authed - Also replaced the deleted Doc.bind 'Add Dex' --- client/webserver/site/src/html/bodybuilder.tmpl | 2 +- client/webserver/site/src/js/settings.ts | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/client/webserver/site/src/html/bodybuilder.tmpl b/client/webserver/site/src/html/bodybuilder.tmpl index 2bd698057a..ac9cad80ff 100644 --- a/client/webserver/site/src/html/bodybuilder.tmpl +++ b/client/webserver/site/src/html/bodybuilder.tmpl @@ -97,7 +97,7 @@ [[[Market Making]]] - + [[[Settings]]] diff --git a/client/webserver/site/src/js/settings.ts b/client/webserver/site/src/js/settings.ts index 7f58bb3d64..66a48a2a51 100644 --- a/client/webserver/site/src/js/settings.ts +++ b/client/webserver/site/src/js/settings.ts @@ -61,6 +61,11 @@ export default class SettingsPage extends BasePage { app().showPopups = show }) + Doc.bind(page.addADex, 'click', () => { + this.dexAddrForm.refresh() + this.showForm(page.dexAddrForm) + }) + this.fiatRateSources.forEach(src => { Doc.bind(src, 'change', async () => { const res = await postJSON('/api/toggleratesource', { From 83d7766a4d7af0bdce0ccaeab8aa054db71604cd Mon Sep 17 00:00:00 2001 From: dev-warrior777 <> Date: Mon, 2 Dec 2024 18:11:05 +0800 Subject: [PATCH 6/8] client,webserver: more fitting place to inject app.Version Also: - Translation string 'BUILD ID' is no longer used. - 'BUILD ID' => 'Version' - Translations updated to mean Version - not Build Id. except arabic as I cannot handle the input method to edit arabic as the arrow/BS keys go the wrong way in the editor. And I do not understand how the editor concatenates arabic strings. Meaning left as previously translated: Build Id. --- client/app/config.go | 4 ++-- client/cmd/bisonw-desktop/app.go | 2 +- client/cmd/bisonw-desktop/config.go | 2 -- client/cmd/bisonw/config.go | 1 - client/cmd/bisonw/main.go | 2 +- client/webserver/locales/ar.go | 2 +- client/webserver/locales/de-de.go | 2 +- client/webserver/locales/en-us.go | 2 +- client/webserver/locales/pl-pl.go | 2 +- client/webserver/locales/pt-br.go | 2 +- client/webserver/locales/zh-cn.go | 2 +- client/webserver/site/src/html/settings.tmpl | 2 +- client/webserver/webserver.go | 9 +++++---- client/webserver/webserver_test.go | 9 +++------ 14 files changed, 19 insertions(+), 24 deletions(-) diff --git a/client/app/config.go b/client/app/config.go index 36e145b049..8c19be8755 100644 --- a/client/app/config.go +++ b/client/app/config.go @@ -143,7 +143,6 @@ type Config struct { WebConfig LogConfig MMConfig - AppVersion string // AppData and ConfigPath should be parsed from the command-line, // as it makes no sense to set these in the config file itself. If no values // are assigned, defaults will be used. @@ -163,7 +162,7 @@ type Config struct { // Web creates a configuration for the webserver. This is a Config method // instead of a WebConfig method because Language is an app-level setting used // by both core and rpcserver. -func (cfg *Config) Web(c *core.Core, mm *mm.MarketMaker, log dex.Logger, utc bool) *webserver.Config { +func (cfg *Config) Web(c *core.Core, mm *mm.MarketMaker, log dex.Logger, utc bool, appVersion string) *webserver.Config { addr := cfg.WebAddr host, _, err := net.SplitHostPort(addr) if err == nil && host != "" { @@ -197,6 +196,7 @@ func (cfg *Config) Web(c *core.Core, mm *mm.MarketMaker, log dex.Logger, utc boo NoEmbed: cfg.NoEmbedSite, HttpProf: cfg.HTTPProfile, Language: cfg.Language, + AppVersion: appVersion, } } diff --git a/client/cmd/bisonw-desktop/app.go b/client/cmd/bisonw-desktop/app.go index b7e33fe2cd..8efd6fafcd 100644 --- a/client/cmd/bisonw-desktop/app.go +++ b/client/cmd/bisonw-desktop/app.go @@ -222,7 +222,7 @@ func mainCore() error { }() } - webSrv, err := webserver.New(cfg.Web(clientCore, marketMaker, logMaker.Logger("WEB"), utc), cfg.AppVersion) + webSrv, err := webserver.New(cfg.Web(clientCore, marketMaker, logMaker.Logger("WEB"), utc, app.Version)) if err != nil { return fmt.Errorf("failed creating web server: %w", err) } diff --git a/client/cmd/bisonw-desktop/config.go b/client/cmd/bisonw-desktop/config.go index 36e9eee284..46f7202641 100644 --- a/client/cmd/bisonw-desktop/config.go +++ b/client/cmd/bisonw-desktop/config.go @@ -49,8 +49,6 @@ func configure() (*Config, error) { return nil, err } - cfg.AppVersion = app.Version - // Resolve unset fields. return &cfg, app.ResolveConfig(appData, &cfg.Config) } diff --git a/client/cmd/bisonw/config.go b/client/cmd/bisonw/config.go index 467c16b264..e102adf12e 100644 --- a/client/cmd/bisonw/config.go +++ b/client/cmd/bisonw/config.go @@ -13,7 +13,6 @@ func configure() (*app.Config, error) { // or the version flag was specified. Override any environment variables // with parsed command line flags. iniCfg := app.DefaultConfig - iniCfg.AppVersion = app.Version preCfg := iniCfg if err := app.ParseCLIConfig(&preCfg); err != nil { return nil, err diff --git a/client/cmd/bisonw/main.go b/client/cmd/bisonw/main.go index eb11e5c0d6..065160d832 100644 --- a/client/cmd/bisonw/main.go +++ b/client/cmd/bisonw/main.go @@ -154,7 +154,7 @@ func runCore(cfg *app.Config) error { } if !cfg.NoWeb { - webSrv, err := webserver.New(cfg.Web(clientCore, marketMaker, logMaker.Logger("WEB"), utc), cfg.AppVersion) + webSrv, err := webserver.New(cfg.Web(clientCore, marketMaker, logMaker.Logger("WEB"), utc, app.Version)) if err != nil { return fmt.Errorf("failed creating web server: %w", err) } diff --git a/client/webserver/locales/ar.go b/client/webserver/locales/ar.go index 27f7c264ac..136dd42e7d 100644 --- a/client/webserver/locales/ar.go +++ b/client/webserver/locales/ar.go @@ -137,7 +137,7 @@ var Ar = map[string]*intl.Translation{ "Export Account": {T: "تصدير الحساب"}, "simultaneous_servers_msg": {T: "يدعم عميل منصة المبادلات اللامركزية لديكريد الاستخدام المتزامن لأي عدد من خوادم منصة المبادلات اللامركزية DEX."}, "Change App Password": {T: "تغيير كلمة مرور التطبيق"}, - "Build ID": {T: "معرف البنية"}, + "Version": {T: "معرف البنية"}, "Connect": {T: "اتصل"}, "Send": {T: "ارسال"}, "Deposit": {T: "إيداع"}, diff --git a/client/webserver/locales/de-de.go b/client/webserver/locales/de-de.go index 497f316522..bcf462d8de 100644 --- a/client/webserver/locales/de-de.go +++ b/client/webserver/locales/de-de.go @@ -135,7 +135,7 @@ var DeDE = map[string]*intl.Translation{ "Export Account": {T: "Account exportieren"}, "simultaneous_servers_msg": {T: "Der unterstützt die gleichzeitige Nutzung einer beliebigen Anzahl von DEX-Servern."}, "Change App Password": {T: "App-Passwort ändern"}, - "Build ID": {T: "Version"}, + "Version": {T: "Version"}, "Connect": {T: "Verbinden"}, "Send": {T: "Senden"}, "Deposit": {T: "Einzahlen"}, diff --git a/client/webserver/locales/en-us.go b/client/webserver/locales/en-us.go index 2f8daa2291..799727bfe4 100644 --- a/client/webserver/locales/en-us.go +++ b/client/webserver/locales/en-us.go @@ -167,7 +167,7 @@ var EnUS = map[string]*intl.Translation{ "browser_ntfn_blocked": {T: "Browser notifications are currently blocked. Please unblock this site in your browser to receive notifications."}, "enable_browser_ntfn_info": {T: "Desktop notifications appear even when this window is not active. When you have other applications open this can be helpful as you will be notified on DCRDEX events. Customize below the types of notifications you would like to receive."}, "Save Notifications": {T: "Save Notifications"}, - "Build ID": {T: "Version"}, + "Version": {T: "Version"}, "Connect": {T: "Connect"}, "Send": {T: "Send"}, "Deposit": {T: "Deposit"}, // unused diff --git a/client/webserver/locales/pl-pl.go b/client/webserver/locales/pl-pl.go index d47cf94cb6..fa8898c193 100644 --- a/client/webserver/locales/pl-pl.go +++ b/client/webserver/locales/pl-pl.go @@ -133,7 +133,7 @@ var PlPL = map[string]*intl.Translation{ "Export Account": {T: "Eksportuj konto"}, "simultaneous_servers_msg": {T: "Klient Decred DEX wspiera jednoczesne korzystanie z wielu serwerów DEX."}, "Change App Password": {T: "Zmień hasło aplikacji"}, - "Build ID": {T: "Wersja"}, + "Version": {T: "Wersja"}, "Connect": {T: "Połącz"}, "Withdraw": {T: "Wypłać"}, "Deposit": {T: "Zdeponuj"}, diff --git a/client/webserver/locales/pt-br.go b/client/webserver/locales/pt-br.go index db2ccbcc89..cb9c96c6e5 100644 --- a/client/webserver/locales/pt-br.go +++ b/client/webserver/locales/pt-br.go @@ -133,7 +133,7 @@ var PtBr = map[string]*intl.Translation{ "Export Account": {T: "Exportar Conta"}, "simultaneous_servers_msg": {T: "O cliente da DEX suporta simultâneos números de servidores DEX."}, "Change App Password": {T: "Trocar Senha do aplicativo"}, - "Build ID": {T: "Versão"}, + "Version": {T: "Versão"}, "Connect": {T: "Conectar"}, "Withdraw": {T: "Retirar"}, "Deposit": {T: "Depositar"}, diff --git a/client/webserver/locales/zh-cn.go b/client/webserver/locales/zh-cn.go index 4adc2fe42d..01194cf367 100644 --- a/client/webserver/locales/zh-cn.go +++ b/client/webserver/locales/zh-cn.go @@ -135,7 +135,7 @@ var ZhCN = map[string]*intl.Translation{ "Export Account": {T: "退出账户"}, "simultaneous_servers_msg": {T: "Decred DEX 客户端支持同时使用任意数量的 DEX 服务器。"}, "Change App Password": {T: "更改应用程序密码"}, - "Build ID": {T: "版本"}, + "Version": {T: "版本"}, "Connect": {T: "连接"}, "Send": {T: "发送"}, "Deposit": {T: "存款"}, diff --git a/client/webserver/site/src/html/settings.tmpl b/client/webserver/site/src/html/settings.tmpl index 2c4b75f61e..48d992fb91 100644 --- a/client/webserver/site/src/html/settings.tmpl +++ b/client/webserver/site/src/html/settings.tmpl @@ -80,7 +80,7 @@ [[[Redeem game code]]] {{$version := .AppVersion}} -

[[[Build ID]]]: {{$version}}

+

[[[Version]]]: {{$version}}

diff --git a/client/webserver/webserver.go b/client/webserver/webserver.go index 9b2ab7a4ad..afed803691 100644 --- a/client/webserver/webserver.go +++ b/client/webserver/webserver.go @@ -238,8 +238,9 @@ type Config struct { // should be used by default since site files from older distributions may // be present on the disk. When NoEmbed is true, this also implies reloading // and execution of html templates on each request. - NoEmbed bool - HttpProf bool + NoEmbed bool + HttpProf bool + AppVersion string } type valStamp struct { @@ -277,7 +278,7 @@ type WebServer struct { // New is the constructor for a new WebServer. CustomSiteDir in the Config can // be left blank, in which case a handful of default locations will be checked. // This will work in most cases. -func New(cfg *Config, appVersion string) (*WebServer, error) { +func New(cfg *Config) (*WebServer, error) { log = cfg.Logger // Only look for files on disk if NoEmbed is set. This is necessary since @@ -393,7 +394,7 @@ func New(cfg *Config, appVersion string) (*WebServer, error) { cachedPasswords: make(map[string]*cachedPassword), bondBuf: map[uint32]valStamp{}, useDEXBranding: useDEXBranding, - appVersion: appVersion, + appVersion: cfg.AppVersion, } s.lang.Store(lang) diff --git a/client/webserver/webserver_test.go b/client/webserver/webserver_test.go index 5a24943f2b..40cbf0d52c 100644 --- a/client/webserver/webserver_test.go +++ b/client/webserver/webserver_test.go @@ -391,13 +391,12 @@ func newTServer(t *testing.T, start bool) (*WebServer, *TCore, func()) { t.Helper() c := &TCore{} var shutdown func() - var appVersion = "1.0.2+release.local" ctx, killCtx := context.WithCancel(tCtx) s, err := New(&Config{ Core: c, Addr: "127.0.0.1:0", Logger: tLogger, - }, appVersion) + }) if err != nil { t.Fatalf("error creating server: %v", err) } @@ -474,14 +473,13 @@ func TestNew_siteError(t *testing.T) { t.Fatalf("Cannot cd to %q", dir) } - var appVersion = "1.0.2+release.local" c := &TCore{} _, err = New(&Config{ Core: c, Addr: "127.0.0.1:0", Logger: tLogger, NoEmbed: true, // this tests locating on-disk files, not the embedded ones - }, appVersion) + }) if err == nil || !strings.HasPrefix(err.Error(), "no HTML template files found") { t.Errorf("Should have failed to start with no site folder.") } @@ -497,12 +495,11 @@ func TestConnectBindError(t *testing.T) { defer shutdown() tAddr := s0.addr - var appVersion = "1.0.2+release.local" s, err := New(&Config{ Core: &TCore{}, Addr: tAddr, Logger: tLogger, - }, appVersion) + }) if err != nil { t.Fatalf("error creating server: %v", err) } From cf944a5c9d099150bc5c27e7f71e3ebbdd716fb5 Mon Sep 17 00:00:00 2001 From: dev-warrior777 <> Date: Mon, 2 Dec 2024 20:55:20 +0800 Subject: [PATCH 7/8] webserver,test: fix live_test.go --- client/webserver/live_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/webserver/live_test.go b/client/webserver/live_test.go index 85ba7b0b75..cae2faf0c1 100644 --- a/client/webserver/live_test.go +++ b/client/webserver/live_test.go @@ -2692,7 +2692,6 @@ func TestServer(t *testing.T) { tCore.PostBond(&core.PostBondForm{Addr: firstDEX, Bond: 1, Asset: &assetID}) } - var appVersion = "1.0.2+release.local" s, err := New(&Config{ Core: tCore, MarketMaker: &TMarketMaker{ @@ -2704,7 +2703,7 @@ func TestServer(t *testing.T) { Logger: logger, NoEmbed: true, // use files on disk, and reload on each page load HttpProf: true, - }, appVersion) + }) if err != nil { t.Fatalf("error creating server: %v", err) } From 29fbf7cd3fedd8aa8bcfb06292586fa184e47cef Mon Sep 17 00:00:00 2001 From: dev-warrior777 <> Date: Thu, 5 Dec 2024 18:26:20 +0800 Subject: [PATCH 8/8] client,webserver: webpack build ID used as browser cache ID. - Emit a webpack build ID when building site and store in webpack-build-id.txt - Embed the webpack build ID into bodybuilder as a url query string:- webpackBuildIdQuery fetches latest webpack build from the webpack-build-id.txt file in app site directory and makes it available to append to the main css link and to the main script link in bodybuilder; this should cause no reload of the main css/js files if they are already cached by the browser. If webpackBuildIdFile is not found return a fallback query that will make the browser reload css/js. - Some eslint in webpack dir. --- .gitignore | 1 + .../webserver/site/src/html/bodybuilder.tmpl | 4 +- client/webserver/site/src/js/app.ts | 6 ++- client/webserver/site/src/js/locales.ts | 6 +-- client/webserver/site/src/js/registry.ts | 1 + client/webserver/site/webpack/analyze.js | 2 +- client/webserver/site/webpack/common.js | 27 +++++++++++--- client/webserver/site/webpack/dev.js | 2 +- client/webserver/site/webpack/prod.js | 2 +- client/webserver/template.go | 37 +++++++++++++++++++ 10 files changed, 73 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 0e82613dfd..38453a6532 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,7 @@ dex/testing/loadbot/loadbot bin/ bin-v*/ client/webserver/site/template-builder/template-builder +client/webserver/site/webpack-build-id.txt dex/testing/btc/harnesschain.tar.gz client/asset/btc/electrum/example/server/server client/asset/btc/electrum/example/wallet/wallet diff --git a/client/webserver/site/src/html/bodybuilder.tmpl b/client/webserver/site/src/html/bodybuilder.tmpl index ac9cad80ff..8fa851e01a 100644 --- a/client/webserver/site/src/html/bodybuilder.tmpl +++ b/client/webserver/site/src/html/bodybuilder.tmpl @@ -9,7 +9,7 @@ {{.Title}} - + - + {{end}} diff --git a/client/webserver/site/src/js/app.ts b/client/webserver/site/src/js/app.ts index 61c4140b0b..642af9a56d 100644 --- a/client/webserver/site/src/js/app.ts +++ b/client/webserver/site/src/js/app.ts @@ -161,6 +161,7 @@ export default class Application { authed: boolean user: User seedGenTime: number + webpackBuildID: string showPopups: boolean loggers: Record recorders: Record @@ -184,13 +185,14 @@ export default class Application { this.notes = [] this.pokes = [] this.seedGenTime = 0 + this.webpackBuildID = process.env.WEBPACK_BUILD_ID || '' this.noteReceivers = [] this.fiatRatesMap = {} this.showPopups = State.fetchLocal(State.popupsLK) === '1' this.txHistoryMap = {} this.requiredActions = {} - console.log('Bison Wallet') + console.log('Bison Wallet', 'Webpack Build Id:', this.webpackBuildID) // Set Bootstrap dark theme attribute if dark mode is enabled. if (State.isDark()) { @@ -259,7 +261,7 @@ export default class Application { // Don't fetch the user until we know what page we're on. await this.fetchUser() const ignoreCachedLocale = process.env.NODE_ENV === 'development' - await intl.loadLocale(this.lang, ignoreCachedLocale) + await intl.loadLocale(this.lang, this.webpackBuildID, ignoreCachedLocale) // The application is free to respond with a page that differs from the // one requested in the omnibox, e.g. routing though a login page. Set the // current URL state based on the actual page. diff --git a/client/webserver/site/src/js/locales.ts b/client/webserver/site/src/js/locales.ts index 561787eec1..47f3abf4fd 100644 --- a/client/webserver/site/src/js/locales.ts +++ b/client/webserver/site/src/js/locales.ts @@ -222,16 +222,16 @@ export const ID_DELETE_BOT = 'DELETE_BOT' let locale: Locale -export async function loadLocale (lang: string, skipCache: boolean) { +export async function loadLocale (lang: string, buildID: string, skipCache: boolean) { if (!skipCache) { const specs = State.fetchLocal(State.localeSpecsKey) - if (specs && specs.lang === lang) { + if (specs && specs.lang === lang && specs.webpackBuildID === buildID) { // not stale locale = State.fetchLocal(State.localeKey) return } } locale = await postJSON('/api/locale', lang) - State.storeLocal(State.localeSpecsKey, { lang }) + State.storeLocal(State.localeSpecsKey, { lang, buildID }) State.storeLocal(State.localeKey, locale) } diff --git a/client/webserver/site/src/js/registry.ts b/client/webserver/site/src/js/registry.ts index d4e9c5fcd9..bc4bcaa680 100644 --- a/client/webserver/site/src/js/registry.ts +++ b/client/webserver/site/src/js/registry.ts @@ -1275,6 +1275,7 @@ export interface Application { exchanges: Record fiatRatesMap: Record showPopups: boolean + webpackBuildID: string authed: boolean start (): Promise reconnected (): void diff --git a/client/webserver/site/webpack/analyze.js b/client/webserver/site/webpack/analyze.js index a87cdb414e..185e1d3251 100644 --- a/client/webserver/site/webpack/analyze.js +++ b/client/webserver/site/webpack/analyze.js @@ -8,7 +8,7 @@ module.exports = merge(common, { rules: [{ test: /\.ts$/, use: 'ts-loader', - exclude: /node_modules/, + exclude: /node_modules/ }] }, optimization: { diff --git a/client/webserver/site/webpack/common.js b/client/webserver/site/webpack/common.js index c279913ac8..608a477e20 100644 --- a/client/webserver/site/webpack/common.js +++ b/client/webserver/site/webpack/common.js @@ -5,10 +5,24 @@ const MiniCssExtractPlugin = require('mini-css-extract-plugin') const StyleLintPlugin = require('stylelint-webpack-plugin') const ESLintPlugin = require('eslint-webpack-plugin') -const child_process = require('child_process') +const fs = require('node:fs') +const buildIdFilename = 'webpack-build-id.txt' + +function randBuildId () { + const buildID = JSON.stringify(Math.floor(Math.random() * 1000000000)).trim() + console.log('WEBPACK_BUILD_ID:', buildID) + fs.writeFile(buildIdFilename, buildID, err => { + if (err) { + console.error(err) + } else { + console.log(' ', buildID, ' written to ', buildIdFilename) + } + }) + return buildID +} module.exports = { - target: "web", + target: 'web', module: { rules: [ { @@ -26,7 +40,7 @@ module.exports = { { loader: 'sass-loader', options: { - implementation: require("sass"), // dart-sass + implementation: require('sass'), // dart-sass sourceMap: true } } @@ -35,12 +49,15 @@ module.exports = { ] }, plugins: [ + new webpack.DefinePlugin({ + 'process.env.WEBPACK_BUILD_ID': randBuildId() + }), new CleanWebpackPlugin(), new MiniCssExtractPlugin({ filename: '../dist/style.css' }), new StyleLintPlugin({ - threads: true, + threads: true }), new ESLintPlugin({ extensions: ['ts'], @@ -53,7 +70,7 @@ module.exports = { publicPath: '/dist/' }, resolve: { - extensions: ['.ts', ".js"], + extensions: ['.ts', '.js'] }, // Fixes weird issue with watch script. See // https://github.com/webpack/webpack/issues/2297#issuecomment-289291324 diff --git a/client/webserver/site/webpack/dev.js b/client/webserver/site/webpack/dev.js index dbfa29db19..d4fdf226a6 100644 --- a/client/webserver/site/webpack/dev.js +++ b/client/webserver/site/webpack/dev.js @@ -7,7 +7,7 @@ module.exports = merge(common, { rules: [{ test: /\.ts$/, use: 'ts-loader', - exclude: /node_modules/, + exclude: /node_modules/ }] }, devtool: 'inline-source-map' diff --git a/client/webserver/site/webpack/prod.js b/client/webserver/site/webpack/prod.js index e64ddd5137..2e42708116 100644 --- a/client/webserver/site/webpack/prod.js +++ b/client/webserver/site/webpack/prod.js @@ -9,7 +9,7 @@ module.exports = merge(common, { usedExports: true, minimize: true, minimizer: [ - `...`, // extend webpack 5's TerserPlugin + '...', // extend webpack 5's TerserPlugin new CssMinimizerPlugin({}) ] }, diff --git a/client/webserver/template.go b/client/webserver/template.go index bd3eb7b50e..c7d12b3f38 100644 --- a/client/webserver/template.go +++ b/client/webserver/template.go @@ -9,6 +9,7 @@ import ( "html/template" "io/fs" "os" + "path/filepath" "strings" "decred.org/dcrdex/client/intl" @@ -17,6 +18,8 @@ import ( "golang.org/x/text/language" ) +const webpackBuildIdFile = "webpack-build-id.txt" + // pageTemplate holds the information necessary to process a template. Also // holds information necessary to reload the templates for development. type pageTemplate struct { @@ -184,6 +187,37 @@ func (t *templates) exec(name string, data any) (string, error) { return page.String(), err } +// webpackBuildIdQuery fetches latest webpack build from the webpack-build-id.txt +// file in app site directory and makes it available to append to the main css +// link and to the main script link in bodybuilder; this should cause no reload +// of the main css/js files if they are already cached by the browser. +// If webpackBuildIdFile is not found return a fallback query that will make the +// browser reload css/js. +var webpackBuildIdQuery = func() string { + var fallbackQueryStr = "?v=1" + d, _ := os.Getwd() + cwd := filepath.Base(d) + if cwd != "bisonw" { + return fallbackQueryStr + } + d = filepath.Dir(d) + cmd := filepath.Base(d) + if cmd != "cmd" { + return fallbackQueryStr + } + d = filepath.Dir(d) + client := filepath.Base(d) + if client != "client" { + return fallbackQueryStr + } + f := filepath.Join(d, "/webserver/site", webpackBuildIdFile) + wpB, err := os.ReadFile(f) + if err != nil { + return fallbackQueryStr + } + return "?v=" + string(wpB) +}() + // templateFuncs are able to be called during template execution. var templateFuncs = template.FuncMap{ "toUpper": strings.ToUpper, @@ -212,4 +246,7 @@ var templateFuncs = template.FuncMap{ } return parts[0] }, + "webpackBuildIdQuery": func() string { + return webpackBuildIdQuery + }, }