Skip to content

Commit

Permalink
Refactor appSettings to accommodate new Tauri v2 API
Browse files Browse the repository at this point in the history
- creates AppSettings class and injects it where needed
- avoids `window` undeclared variable during vite build process
  • Loading branch information
mtsgrd committed Oct 7, 2024
1 parent d84a923 commit 50f450b
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 132 deletions.
40 changes: 14 additions & 26 deletions apps/desktop/src/lib/analytics/analytics.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,22 @@
import { initPostHog } from '$lib/analytics/posthog';
import { initSentry } from '$lib/analytics/sentry';
import { appAnalyticsConfirmed } from '$lib/config/appSettings';
import {
appMetricsEnabled,
appErrorReportingEnabled,
appNonAnonMetricsEnabled
} from '$lib/config/appSettings';
import { AppSettings } from '$lib/config/appSettings';
import posthog from 'posthog-js';

export function initAnalyticsIfEnabled() {
const analyticsConfirmed = appAnalyticsConfirmed();
analyticsConfirmed.onDisk().then((confirmed) => {
export function initAnalyticsIfEnabled(appSettings: AppSettings) {
appSettings.appAnalyticsConfirmed.onDisk().then((confirmed) => {
if (confirmed) {
appErrorReportingEnabled()
.onDisk()
.then((enabled) => {
if (enabled) initSentry();
});
appMetricsEnabled()
.onDisk()
.then((enabled) => {
if (enabled) initPostHog();
});
appNonAnonMetricsEnabled()
.onDisk()
.then((enabled) => {
enabled
? posthog.capture('nonAnonMetricsEnabled')
: posthog.capture('nonAnonMetricsDisabled');
});
appSettings.appErrorReportingEnabled.onDisk().then((enabled) => {
if (enabled) initSentry();
});
appSettings.appMetricsEnabled.onDisk().then((enabled) => {
if (enabled) initPostHog();
});
appSettings.appNonAnonMetricsEnabled.onDisk().then((enabled) => {
enabled
? posthog.capture('nonAnonMetricsEnabled')
: posthog.capture('nonAnonMetricsDisabled');
});
}
});
}
163 changes: 75 additions & 88 deletions apps/desktop/src/lib/config/appSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,95 +8,82 @@
import { createStore } from '@tauri-apps/plugin-store';
import { writable, type Writable } from 'svelte/store';

const store = createStore('settings.json', { autoSave: true });

/**
* Persisted confirmation that user has confirmed their analytics settings.
*/
export function appAnalyticsConfirmed() {
return persisted(false, 'appAnalyticsConfirmed');
}

/**
* Provides a writable store for obtaining or setting the current state of application metrics.
* The application metrics can be enabled or disabled by setting the value of the store to true or false.
* @returns A writable store with the appMetricsEnabled config.
*/
export function appMetricsEnabled() {
return persisted(true, 'appMetricsEnabled');
}

/**
* Provides a writable store for obtaining or setting the current state of application error reporting.
* The application error reporting can be enabled or disabled by setting the value of the store to true or false.
* @returns A writable store with the appErrorReportingEnabled config.
*/
export function appErrorReportingEnabled() {
return persisted(true, 'appErrorReportingEnabled');
}

/**
* Provides a writable store for obtaining or setting the current state of non-anonemous application metrics.
* The setting can be enabled or disabled by setting the value of the store to true or false.
* @returns A writable store with the appNonAnonMetricsEnabled config.
*/
export function appNonAnonMetricsEnabled() {
return persisted(false, 'appNonAnonMetricsEnabled');
}

function persisted<T>(initial: T, key: string): Writable<T> & { onDisk: () => Promise<T> } {
async function setAndPersist(value: T, set: (value: T) => void) {
const storeInstance = await store;
await storeInstance.set(key, value);
await storeInstance.save();

set(value);
}

async function synchronize(set: (value: T) => void): Promise<void> {
const value = await storeValueWithDefault(initial, key);
set(value);
}

function update() {
throw 'Not implemented';
}

const thisStore = writable<T>(initial, (set) => {
synchronize(set);
});

async function set(value: T) {
setAndPersist(value, thisStore.set);
}

async function onDisk() {
return await storeValueWithDefault(initial, key);
}

const subscribe = thisStore.subscribe;

return {
subscribe,
set,
update,
onDisk
};
}

async function storeValueWithDefault<T>(initial: T, key: string): Promise<T> {
const storeInstance = await store;
try {
await storeInstance.load();
} catch (e) {
// If file does not exist, reset it
storeInstance.reset();
export class AppSettings {
// TODO: Remove this once `autoSave: boolean` is upstreamed.
// @ts-expect-error ts-2322
diskStore = createStore('settings.json', { autoSave: 1 });
constructor() {}

/**
* Persisted confirmation that user has confirmed their analytics settings.
*/
readonly appAnalyticsConfirmed = this.persisted(false, 'appAnalyticsConfirmed');

/**
* Provides a writable store for obtaining or setting the current state of application metrics.
* The application metrics can be enabled or disabled by setting the value of the store to true or false.
* @returns A writable store with the appMetricsEnabled config.
*/
readonly appMetricsEnabled = this.persisted(true, 'appMetricsEnabled');

/**
* Provides a writable store for obtaining or setting the current state of application error reporting.
* The application error reporting can be enabled or disabled by setting the value of the store to true or false.
* @returns A writable store with the appErrorReportingEnabled config.
*/
readonly appErrorReportingEnabled = this.persisted(true, 'appErrorReportingEnabled');

/**
* Provides a writable store for obtaining or setting the current state of non-anonemous application metrics.
* The setting can be enabled or disabled by setting the value of the store to true or false.
* @returns A writable store with the appNonAnonMetricsEnabled config.
*/
readonly appNonAnonMetricsEnabled = this.persisted(false, 'appNonAnonMetricsEnabled');

private persisted<T>(initial: T, key: string): Writable<T> & { onDisk: () => Promise<T> } {
const diskStore = this.diskStore;
const storeValueWithDefault = this.storeValueWithDefault.bind(this);

const keySpecificStore = writable<T>(initial, (set) => {
synchronize(set);
});

const subscribe = keySpecificStore.subscribe;

async function setAndPersist(value: T, set: (value: T) => void) {
const store = await diskStore;
store.set(key, value);
set(value);
}

async function synchronize(set: (value: T) => void): Promise<void> {
const value = await storeValueWithDefault(initial, key);
set(value);
}

async function set(value: T) {
setAndPersist(value, keySpecificStore.set);
}

async function onDisk() {
return await storeValueWithDefault(initial, key);
}

function update() {
throw 'Not implemented';
}

return { subscribe, set, update, onDisk };
}
const stored = (await storeInstance.get(key)) as T;

if (stored === null) {
return initial;
} else {
return stored;
async storeValueWithDefault<T>(initial: T, key: string): Promise<T> {
const store = await this.diskStore;
try {
await store.load();
} catch (e) {
store.reset();
}
const stored = (await store.get(key)) as T;
return stored === null ? initial : stored;
}
}
14 changes: 6 additions & 8 deletions apps/desktop/src/lib/settings/AnalyticsSettings.svelte
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
<script lang="ts">
import SectionCard from '$lib/components/SectionCard.svelte';
import {
appErrorReportingEnabled,
appMetricsEnabled,
appNonAnonMetricsEnabled
} from '$lib/config/appSettings';
import { AppSettings } from '$lib/config/appSettings';
import Link from '$lib/shared/Link.svelte';
import Toggle from '$lib/shared/Toggle.svelte';
import { getContext } from '$lib/utils/context';
const errorReportingEnabled = appErrorReportingEnabled();
const metricsEnabled = appMetricsEnabled();
const nonAnonMetricsEnabled = appNonAnonMetricsEnabled();
const appSettings = getContext(AppSettings);
const errorReportingEnabled = appSettings.appErrorReportingEnabled;
const metricsEnabled = appSettings.appMetricsEnabled;
const nonAnonMetricsEnabled = appSettings.appNonAnonMetricsEnabled;
</script>

<section class="analytics-settings">
Expand Down
10 changes: 4 additions & 6 deletions apps/desktop/src/lib/topics/service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { persisted } from '$lib/persisted/persisted';
import { get, type Readable } from 'svelte/store';
import { get, type Readable, type Writable } from 'svelte/store';
import type { Project } from '$lib/backend/projects';
import type { GitHostIssueService } from '$lib/gitHost/interface/gitHostIssueService';

Expand All @@ -12,15 +12,13 @@ export type Topic = {
};

export class TopicService {
topics = persisted<Topic[]>([], this.localStorageKey);
topics: Writable<Topic[]>;

constructor(
private project: Project,
private issueService: Readable<GitHostIssueService | undefined>
) {}

private get localStorageKey(): string {
return `TopicService--${this.project.id}`;
) {
this.topics = persisted<Topic[]>([], `TopicService--${this.project.id}`);
}

create(title: string, body: string, hasIssue: boolean = false): Topic {
Expand Down
2 changes: 2 additions & 0 deletions apps/desktop/src/routes/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import AppUpdater from '$lib/components/AppUpdater.svelte';
import PromptModal from '$lib/components/PromptModal.svelte';
import ShareIssueModal from '$lib/components/ShareIssueModal.svelte';
import { AppSettings } from '$lib/config/appSettings';
import {
createGitHubUserServiceStore as createGitHubUserServiceStore,
GitHubUserService
Expand Down Expand Up @@ -63,6 +64,7 @@
setContext(AIPromptService, data.aiPromptService);
setContext(LineManagerFactory, data.lineManagerFactory);
setContext(StackingLineManagerFactory, data.stackingLineManagerFactory);
setContext(AppSettings, data.appSettings);
setNameNormalizationServiceContext(new IpcNameNormalizationService(invoke));
Expand Down
5 changes: 4 additions & 1 deletion apps/desktop/src/routes/+layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ProjectService } from '$lib/backend/projects';
import { PromptService } from '$lib/backend/prompt';
import { Tauri } from '$lib/backend/tauri';
import { UpdaterService } from '$lib/backend/updater';
import { AppSettings } from '$lib/config/appSettings';
import { RemotesService } from '$lib/remotes/service';
import { RustSecretService } from '$lib/secrets/secretsService';
import { UserService } from '$lib/stores/user';
Expand All @@ -25,7 +26,8 @@ export const csr = true;

// eslint-disable-next-line
export const load: LayoutLoad = async () => {
initAnalyticsIfEnabled();
const appSettings = new AppSettings();
initAnalyticsIfEnabled(appSettings);

// TODO: Find a workaround to avoid this dynamic import
// https://github.com/sveltejs/kit/issues/905
Expand All @@ -47,6 +49,7 @@ export const load: LayoutLoad = async () => {
const stackingLineManagerFactory = new StackingLineManagerFactory();

return {
appSettings,
authService,
cloud: httpClient,
projectService,
Expand Down
6 changes: 4 additions & 2 deletions apps/desktop/src/routes/onboarding/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
import newProjectSvg from '$lib/assets/illustrations/new-project.svg?raw';
import DecorativeSplitView from '$lib/components/DecorativeSplitView.svelte';
import Welcome from '$lib/components/Welcome.svelte';
import { appAnalyticsConfirmed } from '$lib/config/appSettings';
import { AppSettings } from '$lib/config/appSettings';
import AnalyticsConfirmation from '$lib/settings/AnalyticsConfirmation.svelte';
import { getContext } from '$lib/utils/context';
const analyticsConfirmed = appAnalyticsConfirmed();
const appSettings = getContext(AppSettings);
const analyticsConfirmed = appSettings.appAnalyticsConfirmed;
</script>

<DecorativeSplitView img={$analyticsConfirmed ? newProjectSvg : analyticsSvg}>
Expand Down
2 changes: 1 addition & 1 deletion crates/gitbutler-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ tauri-plugin-os = "^2.0.0"
tauri-plugin-process = "^2.0.0"
tauri-plugin-shell = "^2.0.0"
tauri-plugin-single-instance = { version = "^2.0.0" }
tauri-plugin-store = { version = "^2.0.0" }
tauri-plugin-store = { version = "^2.0.1" }
tauri-plugin-updater = "^2.0.0"
tauri-plugin-window-state = { version = "^2.0.0" }
parking_lot.workspace = true
Expand Down

0 comments on commit 50f450b

Please sign in to comment.