From cb4c2be0baafed958013cbb2167426ada1c2e20f Mon Sep 17 00:00:00 2001 From: Tadas Krivickas Date: Thu, 3 Jun 2021 09:41:37 +0300 Subject: [PATCH] Upgrade mobx to 6.x --- package.json | 4 +-- src/config/filters.ts | 16 +++++----- src/config/store.ts | 22 ++++++++------ src/connection/store.ts | 44 ++++++++++++++------------- src/daemon/store.ts | 30 +++++++++--------- src/feedback/store.ts | 10 +++--- src/identity/store.ts | 28 +++++++++-------- src/navigation/routerStore.ts | 11 +++++-- src/navigation/store.ts | 24 ++++++++------- src/payment/store.ts | 54 ++++++++++++++++++--------------- src/proposals/store.ts | 57 +++++++++++++++++------------------ src/referral/store.ts | 26 ++++++++-------- src/store.ts | 8 +++-- tsconfig.json | 3 +- yarn.lock | 16 +++++----- 15 files changed, 188 insertions(+), 165 deletions(-) diff --git a/package.json b/package.json index 9b57ceae..39d4d89a 100644 --- a/package.json +++ b/package.json @@ -35,9 +35,9 @@ "history": "^4.10.1", "lodash": "^4.17.21", "mkdirp": "^1.0.4", - "mobx": "^5.15.6", + "mobx": "^6.3.2", "mobx-logger": "^0.7.1", - "mobx-react-lite": "^2.2.2", + "mobx-react-lite": "^3.2.0", "mysterium-vpn-js": "^13.0.1", "node-machine-id": "^1.1.12", "open": "^7.0.0", diff --git a/src/config/filters.ts b/src/config/filters.ts index c05b3d6f..24ce70db 100644 --- a/src/config/filters.ts +++ b/src/config/filters.ts @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ -import { action, computed, reaction } from "mobx" +import { action, computed, makeObservable, reaction } from "mobx" import { QualityLevel } from "mysterium-vpn-js" import { RootStore } from "../store" @@ -16,6 +16,14 @@ export class Filters { root: RootStore constructor(root: RootStore) { + makeObservable(this, { + priceCeiling: computed, + config: computed, + setPartial: action, + initialized: computed, + defaults: computed, + reset: action, + }) this.root = root } @@ -40,7 +48,6 @@ export class Filters { } } - @computed get priceCeiling(): PriceCeiling | undefined { const consumerConfig = this.root.config.defaultConfig.payments?.consumer if (!consumerConfig || !consumerConfig["price-hour-max"] || !consumerConfig["price-gib-max"]) { @@ -52,22 +59,18 @@ export class Filters { } } - @computed get config(): ProposalFilters { return this.root.config.config.desktop?.filters || {} } - @action setPartial = (filters: ProposalFilters): Promise => { return this.root.config.setPartial({ filters }) } - @computed get initialized(): boolean { return this.config.price?.perhour != null } - @computed get defaults(): ProposalFilters { const ceil = this.priceCeiling return { @@ -86,7 +89,6 @@ export class Filters { } } - @action reset = (): Promise => { return this.setPartial(this.defaults) } diff --git a/src/config/store.ts b/src/config/store.ts index bb413487..b988352d 100644 --- a/src/config/store.ts +++ b/src/config/store.ts @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ -import { action, computed, observable, reaction, runInAction } from "mobx" +import { action, computed, makeObservable, observable, reaction, runInAction } from "mobx" import { DNSOption, QualityLevel } from "mysterium-vpn-js" import * as termsPackageJson from "@mysteriumnetwork/terms/package.json" import * as _ from "lodash" @@ -55,17 +55,25 @@ export interface PriceCeiling { } export class ConfigStore { - @observable config: Config = { desktop: {} } - @observable loaded = false - @observable defaultConfig: Config = { desktop: {} } root: RootStore constructor(root: RootStore) { this.root = root + makeObservable(this, { + config: observable, + loaded: observable, + defaultConfig: observable, + fetchConfig: action, + agreeToTerms: action, + setDnsOption: action, + dnsOption: computed, + persistConfig: action, + setPartial: action, + }) } setupReactions(): void { @@ -80,7 +88,6 @@ export class ConfigStore { ) } - @action fetchConfig = async (): Promise => { const [config, defaultConfig] = await Promise.all([tequilapi.userConfig(), tequilapi.defaultConfig()]) runInAction(() => { @@ -102,7 +109,6 @@ export class ConfigStore { }) } - @action agreeToTerms = async (): Promise => { const data: Config = { ...this.config, @@ -124,7 +130,6 @@ export class ConfigStore { return !!version && !!at && version == termsPackageJson.version } - @action setDnsOption = async (value: string): Promise => { await tequilapi.updateUserConfig({ data: { "desktop.dns": value }, @@ -132,12 +137,10 @@ export class ConfigStore { await this.fetchConfig() } - @computed get dnsOption(): DNSOption { return this.config.desktop?.dns ?? "1.1.1.1" } - @action persistConfig = _.debounce(async () => { const cfg = this.config log.info("Persisting user configuration:", JSON.stringify(cfg)) @@ -147,7 +150,6 @@ export class ConfigStore { await this.fetchConfig() }, 3_000) - @action setPartial = async (desktopConfig: DesktopConfig): Promise => { this.config.desktop = _.merge({}, this.config.desktop, desktopConfig) this.persistConfig() diff --git a/src/connection/store.ts b/src/connection/store.ts index 9c2f3c64..9adc9ec4 100644 --- a/src/connection/store.ts +++ b/src/connection/store.ts @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ -import { action, observable, reaction, runInAction } from "mobx" +import { action, makeObservable, observable, reaction, runInAction } from "mobx" import { AppState, ConnectionStatistics, ConnectionStatus, Location, SSEEventType } from "mysterium-vpn-js" import { ipcRenderer } from "electron" import retry from "async-retry" @@ -20,24 +20,39 @@ import { tequilapi } from "../tequilapi" import { AppStateAction, ConnectionAction } from "../analytics/actions" export class ConnectionStore { - @observable connectInProgress = false - @observable gracePeriod = false - @observable status = ConnectionStatus.NOT_CONNECTED - @observable statistics?: ConnectionStatistics - @observable proposal?: UIProposal - @observable location?: Location - @observable originalLocation?: Location root: RootStore constructor(root: RootStore) { + makeObservable(this, { + connectInProgress: observable, + gracePeriod: observable, + status: observable, + statistics: observable, + proposal: observable, + location: observable, + originalLocation: observable, + connect: action, + statusCheck: action, + disconnect: action, + resolveOriginalLocation: action, + resetLocation: action, + resolveLocation: action, + setConnectInProgress: action, + setGracePeriod: action, + setStatus: action, + setProposal: action, + setLocation: action, + setOriginalLocation: action, + setStatistics: action, + }) this.root = root } @@ -81,7 +96,6 @@ export class ConnectionStore { ) } - @action async connect(): Promise { if (!this.root.identity.identity || !this.root.proposals.active) { return @@ -109,7 +123,6 @@ export class ConnectionStore { } } - @action async statusCheck(): Promise { try { if (this.connectInProgress) { @@ -126,7 +139,6 @@ export class ConnectionStore { } } - @action async disconnect(): Promise { userEvent(ConnectionAction.Disconnect, this.root.connection.location?.country) this.setGracePeriod() @@ -137,7 +149,6 @@ export class ConnectionStore { } } - @action async resolveOriginalLocation(): Promise { try { const location = await tequilapi.location() @@ -147,7 +158,6 @@ export class ConnectionStore { } } - @action resetLocation(): void { this.setLocation({ country: "unknown", @@ -160,7 +170,6 @@ export class ConnectionStore { }) } - @action async resolveLocation(): Promise { let location: Location = { country: "unknown", @@ -183,12 +192,10 @@ export class ConnectionStore { this.setLocation(location) } - @action setConnectInProgress = (b: boolean): void => { this.connectInProgress = b } - @action setGracePeriod = (): void => { this.gracePeriod = true setTimeout(() => { @@ -198,27 +205,22 @@ export class ConnectionStore { }, 5000) } - @action setStatus = (s: ConnectionStatus): void => { this.status = s } - @action setProposal = (p?: UIProposal): void => { this.proposal = p } - @action setLocation = (l: Location): void => { this.location = l } - @action setOriginalLocation = (l: Location): void => { this.originalLocation = l } - @action setStatistics = (s?: ConnectionStatistics): void => { this.statistics = s } diff --git a/src/daemon/store.ts b/src/daemon/store.ts index 66908c16..f22c1739 100644 --- a/src/daemon/store.ts +++ b/src/daemon/store.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import { action, observable, reaction, when } from "mobx" +import { action, makeObservable, observable, reaction, when } from "mobx" import { ipcRenderer, remote } from "electron" import { sseConnect } from "../tequila-sse" @@ -34,15 +34,9 @@ export enum StartupStatus { } export class DaemonStore { - @observable statusLoading = false - @observable status = DaemonStatusType.Down - - @observable startupStatus = StartupStatus.CheckingForUpdates - - @observable starting = false eventSource?: EventSource @@ -50,6 +44,20 @@ export class DaemonStore { root: RootStore constructor(root: RootStore) { + makeObservable(this, { + statusLoading: observable, + status: observable, + startupStatus: observable, + starting: observable, + setStartupStatus: action, + healthcheck: action, + update: action, + start: action, + supervisorInstall: action, + setStatus: action, + setStarting: action, + setStatusLoading: action, + }) this.root = root setInterval(async () => { await this.healthcheck() @@ -75,12 +83,10 @@ export class DaemonStore { this.update() } - @action setStartupStatus(status: StartupStatus): void { this.startupStatus = status } - @action async healthcheck(): Promise { if (this.starting) { log.info("Daemon is starting, skipping healthcheck") @@ -101,7 +107,6 @@ export class DaemonStore { this.setStatusLoading(false) } - @action async update(): Promise { ipcRenderer.send(MainIpcListenChannels.Update) ipcRenderer.on(WebIpcListenChannels.UpdateAvailable, () => { @@ -130,7 +135,6 @@ export class DaemonStore { }, 5_000) } - @action async start(): Promise { if (this.starting) { log.info("Already starting") @@ -154,7 +158,6 @@ export class DaemonStore { this.setStarting(false) } - @action async supervisorInstall(): Promise { try { return await supervisor.install() @@ -163,17 +166,14 @@ export class DaemonStore { } } - @action setStatus = (s: DaemonStatusType): void => { this.status = s } - @action setStarting = (s: boolean): void => { this.starting = s } - @action setStatusLoading = (s: boolean): void => { this.statusLoading = s } diff --git a/src/feedback/store.ts b/src/feedback/store.ts index dade7c24..596ac280 100644 --- a/src/feedback/store.ts +++ b/src/feedback/store.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import { action, observable } from "mobx" +import { action, makeObservable, observable } from "mobx" import { Issue } from "mysterium-vpn-js/lib/feedback/issue" import { RootStore } from "../store" @@ -14,14 +14,17 @@ import { tequilapi } from "../tequilapi" export class FeedbackStore { root: RootStore - @observable loading = false constructor(root: RootStore) { + makeObservable(this, { + loading: observable, + setLoading: action, + reportIssue: action, + }) this.root = root } - @action async reportIssue(issue: Issue): Promise { this.setLoading(true) try { @@ -32,7 +35,6 @@ export class FeedbackStore { } } - @action setLoading = (b: boolean): void => { this.loading = b } diff --git a/src/identity/store.ts b/src/identity/store.ts index b2765a82..e8e3ce6a 100644 --- a/src/identity/store.ts +++ b/src/identity/store.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ import { AppState, Identity, SSEEventType } from "mysterium-vpn-js" -import { action, observable, reaction, runInAction } from "mobx" +import { action, makeObservable, observable, reaction, runInAction } from "mobx" import { RootStore } from "../store" import { eventBus } from "../tequila-sse" @@ -16,18 +16,28 @@ import { AppStateAction } from "../analytics/actions" import { eligibleForRegistration, registered } from "./identity" export class IdentityStore { - @observable loading = false - @observable identity?: Identity - @observable unlocked = false - @observable identities: Identity[] = [] root: RootStore constructor(root: RootStore) { + makeObservable(this, { + loading: observable, + identity: observable, + unlocked: observable, + identities: observable, + refreshIdentity: action, + create: action, + unlock: action, + register: action, + registerWithReferralToken: action, + setLoading: action, + setIdentity: action, + setIdentities: action, + }) this.root = root } @@ -97,7 +107,6 @@ export class IdentityStore { ) } - @action refreshIdentity = (identities: Identity[]): void => { if (!this.identity) { return @@ -107,13 +116,11 @@ export class IdentityStore { this.setIdentity(matchingId) } - @action async create(): Promise { appStateEvent(AppStateAction.IdentityCreate) await tequilapi.identityCreate("") } - @action async unlock(): Promise { if (!this.identity) { return @@ -126,14 +133,12 @@ export class IdentityStore { }) } - @action async register(id: Identity): Promise { await this.root.payment.fetchTransactorFees() appStateEvent(AppStateAction.IdentityRegister) return tequilapi.identityRegister(id.id, { stake: 0 }) } - @action async registerWithReferralToken(token: string): Promise { if (!this.identity) { return @@ -148,17 +153,14 @@ export class IdentityStore { } } - @action setLoading = (b: boolean): void => { this.loading = b } - @action setIdentity = (identity?: Identity): void => { this.identity = identity } - @action setIdentities = (identities: Identity[]): void => { this.identities = identities } diff --git a/src/navigation/routerStore.ts b/src/navigation/routerStore.ts index f2ea0ad4..bd7ffa34 100644 --- a/src/navigation/routerStore.ts +++ b/src/navigation/routerStore.ts @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ -import { action, observable, observe } from "mobx" +import { action, makeObservable, observable, observe } from "mobx" import { History, Location, LocationListener, UnregisterCallback } from "history" import { pageview } from "../analytics/analytics" @@ -12,7 +12,6 @@ import { pageview } from "../analytics/analytics" import { AppLocation } from "./locations" export class RouterStore { - @observable location: Location = { pathname: "", search: "", @@ -22,7 +21,13 @@ export class RouterStore { history: SynchronizedHistory | undefined - @action + constructor() { + makeObservable(this, { + location: observable, + updateLocation: action, + }) + } + updateLocation = (newLocation: Location): void => { this.location = newLocation } diff --git a/src/navigation/store.ts b/src/navigation/store.ts index 9dbbbb67..7b5e009d 100644 --- a/src/navigation/store.ts +++ b/src/navigation/store.ts @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ -import { action, computed, observable, observe, reaction } from "mobx" +import { action, computed, makeObservable, observable, observe, reaction } from "mobx" import { ConnectionStatus } from "mysterium-vpn-js" import { ipcRenderer } from "electron" @@ -21,16 +21,25 @@ const connectionInProgress = (status: ConnectionStatus): boolean => { } export class NavigationStore { - @observable welcome = true - @observable menu = false - @observable chat = false root: RootStore constructor(root: RootStore) { + makeObservable(this, { + welcome: observable, + menu: observable, + chat: observable, + showLoading: action, + goHome: action, + determineRoute: action, + showWelcome: action, + dismissWelcome: action, + showMenu: action, + openChat: action, + }) this.root = root } @@ -57,12 +66,10 @@ export class NavigationStore { ) } - @action showLoading = (): void => { this.root.router.push(locations.loading) } - @action goHome = (): void => { if (connectionInProgress(this.root.connection.status)) { this.root.router.push(locations.connection) @@ -71,7 +78,6 @@ export class NavigationStore { } } - @action determineRoute = (): void => { const newLocation = this.determineLocation() if (newLocation) { @@ -100,24 +106,20 @@ export class NavigationStore { return locations.proposals } - @action showWelcome = (): void => { this.welcome = true } - @action dismissWelcome = (): void => { userEvent(OnboardingAction.GetStarted) this.welcome = false this.root.router.push(locations.terms) } - @action showMenu = (show = true): void => { this.menu = show } - @action openChat = (open = true): void => { this.chat = open } diff --git a/src/payment/store.ts b/src/payment/store.ts index 333bd5b8..0d711822 100644 --- a/src/payment/store.ts +++ b/src/payment/store.ts @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ -import { action, computed, observable, reaction, runInAction, when } from "mobx" +import { action, computed, makeObservable, observable, reaction, runInAction, when } from "mobx" import { Currency, Fees, Money, PaymentOrderOptionsResponse, PaymentOrderResponse } from "mysterium-vpn-js" import retry from "async-retry" @@ -27,26 +27,43 @@ export enum OrderStatus { export class PaymentStore { root: RootStore - @observable fees?: Fees - @observable mystToUsdRate?: Money - @observable registrationTopupAmount?: number - @observable topupAmount?: number - @observable currencies: string[] = [] - @observable orderOptions?: PaymentOrderOptionsResponse - @observable paymentCurrency?: string - @observable lightningNetwork = false - @observable order?: PaymentOrderResponse constructor(root: RootStore) { + makeObservable(this, { + fees: observable, + mystToUsdRate: observable, + registrationTopupAmount: observable, + topupAmount: observable, + currencies: observable, + orderOptions: observable, + paymentCurrency: observable, + lightningNetwork: observable, + order: observable, + fetchTransactorFees: action, + fetchMystToUsdRate: action, + fetchCurrencies: action, + registrationFee: computed, + fetchPaymentOptions: action, + orderOptionsValid: computed, + orderMinimumAmount: computed, + createOrder: action, + orderStatus: computed, + clearOrder: action, + topupTotal: computed, + setRegistrationTopupAmount: action, + setPaymentCurrency: action, + setLightningNetwork: action, + setTopupAmount: action, + }) this.root = root } @@ -61,7 +78,6 @@ export class PaymentStore { ) } - @action async fetchTransactorFees(): Promise { const fees = await tequilapi.transactorFees() runInAction(() => { @@ -69,7 +85,6 @@ export class PaymentStore { }) } - @action async fetchMystToUsdRate(): Promise { const res = await tequilapi.exchangeRate("usd") runInAction(() => { @@ -77,7 +92,6 @@ export class PaymentStore { }) } - @action async fetchCurrencies(): Promise { const currencies = await tequilapi.getPaymentOrderCurrencies() runInAction(() => { @@ -89,7 +103,6 @@ export class PaymentStore { }) } - @computed get registrationFee(): number | undefined { if (!this.fees) { return undefined @@ -97,14 +110,13 @@ export class PaymentStore { return Number(fmtMoney({ amount: this.fees.registration, currency: Currency.MYSTTestToken })) } - @action async fetchPaymentOptions(): Promise { const options = await tequilapi.getPaymentOrderOptions() runInAction(() => { this.orderOptions = options }) } - @computed + get orderOptionsValid(): boolean { let valid = !!this.root.identity.identity?.id && !!this.topupAmount && !!this.paymentCurrency if (this.orderOptions?.minimum && this.topupAmount) { @@ -112,7 +124,7 @@ export class PaymentStore { } return valid } - @computed + get orderMinimumAmount(): number { const min = this.orderOptions?.minimum if (!min) { @@ -121,7 +133,6 @@ export class PaymentStore { return Math.round(min) + 1 } - @action async createOrder(): Promise { const id = this.root.identity.identity?.id if (!id) { @@ -172,7 +183,6 @@ export class PaymentStore { ) } - @computed get orderStatus(): OrderStatus { if (!this.order) { return OrderStatus.PENDING @@ -186,7 +196,6 @@ export class PaymentStore { } } - @action clearOrder(): void { this.order = undefined this.setPaymentCurrency(this.currencies[0]) @@ -194,7 +203,6 @@ export class PaymentStore { this.setTopupAmount(undefined) } - @computed get topupTotal(): number | undefined { const reg = this.registrationFee if (!reg) { @@ -203,23 +211,19 @@ export class PaymentStore { return reg + (this.registrationTopupAmount ?? 0) } - @action setRegistrationTopupAmount = (amount?: number): void => { this.registrationTopupAmount = amount } - @action setPaymentCurrency = (currency?: string): void => { this.paymentCurrency = currency this.lightningNetwork = isLightningAvailable(currency) } - @action setLightningNetwork = (use: boolean): void => { this.lightningNetwork = use } - @action setTopupAmount = (amount?: number): void => { this.topupAmount = amount } diff --git a/src/proposals/store.ts b/src/proposals/store.ts index 76e65c5c..f933909d 100644 --- a/src/proposals/store.ts +++ b/src/proposals/store.ts @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ -import { action, computed, observable, reaction, when } from "mobx" +import { action, computed, makeObservable, observable, reaction, when } from "mobx" import { ConnectionStatus, QualityLevel } from "mysterium-vpn-js" import * as _ from "lodash" @@ -28,20 +28,41 @@ export type TransientFilter = { } export class ProposalStore { - @observable loading = false - @observable proposals: UIProposal[] = [] - - @observable active?: UIProposal - - @observable filter: TransientFilter = {} root: RootStore constructor(root: RootStore) { + makeObservable(this, { + loading: observable, + proposals: observable, + active: observable, + filter: observable, + filters: computed, + fetchProposals: action, + setTextFilter: action, + textFiltered: computed, + setPricePerHourMaxFilter: action, + setPricePerHourMaxFilterDebounced: action, + setPricePerGibMaxFilter: action, + setPricePerGibMaxFilterDebounced: action, + setQualityFilter: action, + setIncludeFailed: action, + ipTypeCounts: computed, + setIpTypeFilter: action, + toggleIpTypeFilter: action, + countryCounts: computed, + setCountryFilter: action, + toggleCountryFilter: action, + countryFiltered: computed, + filteredProposals: computed, + toggleActiveProposal: action, + setLoading: action, + setProposals: action, + }) this.root = root } @@ -68,12 +89,10 @@ export class ProposalStore { }, proposalRefreshRate) } - @computed get filters(): ProposalFilters { return this.root.filters.config } - @action async fetchProposals(): Promise { if (this.loading) { return @@ -99,14 +118,12 @@ export class ProposalStore { // Text filter // ##################### - @action setTextFilter(text?: string): void { this.filter.text = text this.setCountryFilter(undefined) userEvent(ProposalViewAction.FilterText, text) } - @computed get textFiltered(): UIProposal[] { const input = this.proposals const filterText = this.filter.text @@ -120,7 +137,6 @@ export class ProposalStore { // Price filter // ##################### - @action async setPricePerHourMaxFilter(pricePerHourMax: number): Promise { await this.root.filters.setPartial({ price: { @@ -131,10 +147,8 @@ export class ProposalStore { userEvent(ProposalViewAction.FilterPriceTime, String(pricePerHourMax)) } - @action setPricePerHourMaxFilterDebounced = _.debounce(this.setPricePerHourMaxFilter, 800) - @action async setPricePerGibMaxFilter(pricePerGibMax: number): Promise { await this.root.filters.setPartial({ price: { @@ -145,14 +159,12 @@ export class ProposalStore { userEvent(ProposalViewAction.FilterPriceData, String(pricePerGibMax)) } - @action setPricePerGibMaxFilterDebounced = _.debounce(this.setPricePerGibMaxFilter, 800) // ##################### // Quality filter // ##################### - @action async setQualityFilter(level: QualityLevel): Promise { await this.root.filters.setPartial({ quality: { level }, @@ -161,7 +173,6 @@ export class ProposalStore { userEvent(ProposalViewAction.FilterQuality, level ? QualityLevel[level] : undefined) } - @action setIncludeFailed(includeFailed: boolean): void { this.root.filters.setPartial({ quality: { @@ -174,15 +185,12 @@ export class ProposalStore { // ##################### // IP type filter // ##################### - - @computed get ipTypeCounts(): { [type: string]: number } { const input = this.proposals const result = _.groupBy(input, (p) => p.ipType) return _.mapValues(result, (ps) => ps.length) } - @action async setIpTypeFilter(ipType?: string): Promise { await this.root.filters.setPartial({ other: { @@ -192,7 +200,6 @@ export class ProposalStore { await this.fetchProposals() } - @action toggleIpTypeFilter(ipType?: string): void { this.setIpTypeFilter(this.filters.other?.["ip-type"] !== ipType ? ipType : "") userEvent(ProposalViewAction.FilterIpType, ipType) @@ -202,26 +209,22 @@ export class ProposalStore { // Country filter // ##################### - @computed get countryCounts(): { [code: string]: number } { const input = this.textFiltered const result = _.groupBy(input, (p) => p.country) return _.mapValues(result, (ps) => ps.length) } - @action async setCountryFilter(countryCode?: string): Promise { this.filter.country = countryCode } - @action toggleCountryFilter(countryCode?: string): void { this.setCountryFilter(this.filter.country !== countryCode ? countryCode : undefined) this.toggleActiveProposal(undefined) userEvent(ProposalViewAction.FilterCountry, countryCode) } - @computed get countryFiltered(): UIProposal[] { const input = this.textFiltered if (!this.filter.country) { @@ -234,7 +237,6 @@ export class ProposalStore { // Resulting list of proposals // ##################### - @computed get filteredProposals(): UIProposal[] { return this.countryFiltered.slice().sort(compareProposal) } @@ -243,18 +245,15 @@ export class ProposalStore { // End of filters // ##################### - @action toggleActiveProposal(proposal?: UIProposal): void { this.active = this.active?.key !== proposal?.key ? proposal : undefined userEvent(ProposalViewAction.SelectProposal, proposal?.country) } - @action setLoading = (b: boolean): void => { this.loading = b } - @action setProposals = (proposals: UIProposal[]): void => { this.proposals = proposals } diff --git a/src/referral/store.ts b/src/referral/store.ts index f3a67017..41c5551a 100644 --- a/src/referral/store.ts +++ b/src/referral/store.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import { action, observable } from "mobx" +import { action, makeObservable, observable } from "mobx" import * as _ from "lodash" import { RootStore } from "../store" @@ -14,18 +14,22 @@ import { parseError } from "../errors/parse" import { tequilapi } from "../tequilapi" export class ReferralStore { - @observable token?: string - - @observable message?: string - - @observable loading = false root: RootStore constructor(root: RootStore) { + makeObservable(this, { + token: observable, + message: observable, + loading: observable, + generateToken: action, + setToken: action, + setMessage: action, + setLoading: action, + }) this.root = root } @@ -33,14 +37,13 @@ export class ReferralStore { log.debug("reserved") } - @action async generateToken(): Promise { const id = this.root.identity.identity?.id if (!id) { return } return _.throttle(async () => { - this.setIsLoading(true) + this.setLoading(true) try { const tokenResponse = await tequilapi.getReferralToken(id) this.setToken(tokenResponse.token) @@ -48,25 +51,22 @@ export class ReferralStore { this.setMessage(parseError(err)) log.error("Referral token generation failed", err) } finally { - this.setIsLoading(false) + this.setLoading(false) } }, 60_000)() } - @action setToken(token: string): void { this.token = token this.message = undefined } - @action setMessage(message?: string): void { this.token = undefined this.message = message } - @action - setIsLoading(b: boolean): void { + setLoading(b: boolean): void { this.loading = b } } diff --git a/src/store.ts b/src/store.ts index ee0bcfee..7d4be96d 100644 --- a/src/store.ts +++ b/src/store.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ import React from "react" -import { action, configure, observable } from "mobx" +import { action, configure, makeObservable, observable } from "mobx" import { ipcRenderer } from "electron" // import { enableLogging } from "mobx-logger" @@ -36,10 +36,13 @@ export class RootStore { feedback: FeedbackStore referral: ReferralStore - @observable showGrid = false constructor() { + makeObservable(this, { + showGrid: observable, + toggleGrid: action, + }) this.navigation = new NavigationStore(this) this.router = new RouterStore() this.daemon = new DaemonStore(this) @@ -70,7 +73,6 @@ export class RootStore { }) } - @action toggleGrid = (): void => { if (isDevelopment()) { this.showGrid = !this.showGrid diff --git a/tsconfig.json b/tsconfig.json index b2229e6a..3cb299c4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,8 @@ "extends": "./node_modules/electron-webpack/tsconfig-base.json", "compilerOptions": { "jsx": "react", - "experimentalDecorators": true, + "experimentalDecorators": false, + "useDefineForClassFields": true, "resolveJsonModule": true } } diff --git a/yarn.lock b/yarn.lock index 82cdae5a..e12eef33 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7113,15 +7113,15 @@ mobx-logger@^0.7.1: resolved "https://registry.yarnpkg.com/mobx-logger/-/mobx-logger-0.7.1.tgz#6be44c726e14433463f5fa566f24f1768e2a9355" integrity sha512-kAcNjzDGjILjvNiVrQZfVY6Bxs5YKt35rtwNuU/uneLq+E9zF5grnGmr95EMqqYSVpE6RjJLID3y3j0yQ/cvRA== -mobx-react-lite@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-2.2.2.tgz#87c217dc72b4e47b22493daf155daf3759f868a6" - integrity sha512-2SlXALHIkyUPDsV4VTKVR9DW7K3Ksh1aaIv3NrNJygTbhXe2A9GrcKHZ2ovIiOp/BXilOcTYemfHHZubP431dg== +mobx-react-lite@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-3.2.0.tgz#331d7365a6b053378dfe9c087315b4e41c5df69f" + integrity sha512-q5+UHIqYCOpBoFm/PElDuOhbcatvTllgRp3M1s+Hp5j0Z6XNgDbgqxawJ0ZAUEyKM8X1zs70PCuhAIzX1f4Q/g== -mobx@^5.15.6: - version "5.15.6" - resolved "https://registry.yarnpkg.com/mobx/-/mobx-5.15.6.tgz#24750af56f87bcf9c3cf82ece4c79eb91bb71968" - integrity sha512-U5nnx3UNdRkUjntpwzO060VWifGVx/JZeu/aMw4y28dTjDNjoY3vNKs6tFNm7z1qIfcPInsd9L9HIm8H0zTDqg== +mobx@^6.3.2: + version "6.3.2" + resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.3.2.tgz#125590961f702a572c139ab69392bea416d2e51b" + integrity sha512-xGPM9dIE1qkK9Nrhevp0gzpsmELKU4MFUJRORW/jqxVFIHHWIoQrjDjL8vkwoJYY3C2CeVJqgvl38hgKTalTWg== move-concurrently@^1.0.1: version "1.0.1"