Skip to content

Commit c0a3806

Browse files
committed
Switch from Tauri backend to new Backend interface
Replace all usage of the old Tauri backend instance with the new unified IBackend interface, as returned from createBackend(). Update all affected services, dependency injections, and imports so they now adhere to the new backend abstraction. Remove references to tauri where possible, and update service constructors and API calls accordingly.
1 parent bf493f5 commit c0a3806

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+388
-252
lines changed

apps/desktop/src/components/AppUpdater.test.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import AppUpdater from '$components/AppUpdater.svelte';
22
import { EventContext } from '$lib/analytics/eventContext';
33
import { PostHogWrapper } from '$lib/analytics/posthog';
4-
import { Tauri } from '$lib/backend/tauri';
4+
import createBackend from '$lib/backend';
55
import { ShortcutService } from '$lib/shortcuts/shortcutService';
66
import { getSettingsdServiceMock } from '$lib/testing/mockSettingsdService';
77
import { UPDATER_SERVICE, UpdaterService } from '$lib/updater/updater';
@@ -12,18 +12,18 @@ import type { Update } from '@tauri-apps/plugin-updater';
1212
describe('AppUpdater', () => {
1313
let updater: UpdaterService;
1414
let context: Map<any, any>;
15-
const tauri = new Tauri();
16-
const shortcuts = new ShortcutService(tauri);
15+
const backend = createBackend();
16+
const shortcuts = new ShortcutService(backend);
1717
const MockSettingsService = getSettingsdServiceMock();
1818
const settingsService = new MockSettingsService();
1919
const eventContext = new EventContext();
2020
const posthog = new PostHogWrapper(settingsService, eventContext);
2121

2222
beforeEach(() => {
2323
vi.useFakeTimers();
24-
updater = new UpdaterService(tauri, posthog, shortcuts);
24+
updater = new UpdaterService(backend, posthog, shortcuts);
2525
context = new Map([[UPDATER_SERVICE._key, updater]]);
26-
vi.spyOn(tauri, 'listen').mockReturnValue(async () => {});
26+
vi.spyOn(backend, 'listen').mockReturnValue(async () => {});
2727
vi.mock('$env/dynamic/public', () => {
2828
return {
2929
env: {
@@ -39,7 +39,7 @@ describe('AppUpdater', () => {
3939
});
4040

4141
test('should be hidden if no update', async () => {
42-
vi.spyOn(tauri, 'checkUpdate').mockReturnValue(
42+
vi.spyOn(backend, 'checkUpdate').mockReturnValue(
4343
mockUpdate({
4444
version: '1'
4545
})
@@ -53,7 +53,7 @@ describe('AppUpdater', () => {
5353
});
5454

5555
test('should display download button', async () => {
56-
vi.spyOn(tauri, 'checkUpdate').mockReturnValue(
56+
vi.spyOn(backend, 'checkUpdate').mockReturnValue(
5757
mockUpdate({
5858
available: true,
5959
version: '1',
@@ -69,7 +69,7 @@ describe('AppUpdater', () => {
6969
});
7070

7171
test('should display up-to-date on manaul check', async () => {
72-
vi.spyOn(tauri, 'checkUpdate').mockReturnValue(
72+
vi.spyOn(backend, 'checkUpdate').mockReturnValue(
7373
mockUpdate({
7474
available: false
7575
})
@@ -83,7 +83,7 @@ describe('AppUpdater', () => {
8383
});
8484

8585
test('should display restart button on install complete', async () => {
86-
vi.spyOn(tauri, 'checkUpdate').mockReturnValue(
86+
vi.spyOn(backend, 'checkUpdate').mockReturnValue(
8787
mockUpdate({
8888
available: true,
8989
version: '2',

apps/desktop/src/components/CloneForm.svelte

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import InfoMessage, { type MessageStyle } from '$components/InfoMessage.svelte';
44
import Section from '$components/Section.svelte';
55
import { POSTHOG_WRAPPER } from '$lib/analytics/posthog';
6-
import { invoke } from '$lib/backend/ipc';
6+
import { GIT_SERVICE } from '$lib/git/gitService';
77
import { PROJECTS_SERVICE } from '$lib/project/projectsService';
88
import { projectPath } from '$lib/routes/routes.svelte';
99
import { parseRemoteUrl } from '$lib/url/gitUrl';
@@ -18,6 +18,7 @@
1818
import { onMount } from 'svelte';
1919
2020
const projectsService = inject(PROJECTS_SERVICE);
21+
const gitService = inject(GIT_SERVICE);
2122
const posthog = inject(POSTHOG_WRAPPER);
2223
2324
let loading = $state(false);
@@ -84,10 +85,7 @@
8485
8586
const targetDir = await join(targetDirPath, remoteUrl.name);
8687
87-
await invoke('git_clone_repository', {
88-
repositoryUrl,
89-
targetDir
90-
});
88+
await gitService.cloneRepo(repositoryUrl, targetDir);
9189
9290
posthog.capture('Repository Cloned', { protocol: remoteUrl.protocol });
9391
const project = await projectsService.addProject(targetDir);

apps/desktop/src/components/CommitSigningForm.svelte

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
import InfoMessage from '$components/InfoMessage.svelte';
33
import Section from '$components/Section.svelte';
44
import SectionCardDisclaimer from '$components/SectionCardDisclaimer.svelte';
5-
import { invoke } from '$lib/backend/ipc';
65
import { GIT_CONFIG_SERVICE } from '$lib/config/gitConfigService';
6+
import { GIT_SERVICE } from '$lib/git/gitService';
77
import { inject } from '@gitbutler/shared/context';
88
import { Button, Link, SectionCard, Select, SelectItem, Textbox, Toggle } from '@gitbutler/ui';
99
@@ -12,6 +12,7 @@
1212
const { projectId }: { projectId: string } = $props();
1313
1414
const gitConfig = inject(GIT_CONFIG_SERVICE);
15+
const gitService = inject(GIT_SERVICE);
1516
1617
let signCommits = $state(false);
1718
@@ -57,8 +58,9 @@
5758
errorMessage = '';
5859
checked = true;
5960
loading = true;
60-
await invoke('check_signing_settings', { projectId: projectId })
61-
.then((_) => {
61+
await gitService
62+
.checkSigningSettings(projectId)
63+
.then(() => {
6264
signCheckResult = true;
6365
})
6466
.catch((err) => {

apps/desktop/src/components/Feed.svelte

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import CliSymLink from '$components/profileSettings/CliSymLink.svelte';
55
import { ACTION_SERVICE } from '$lib/actions/actionService.svelte';
66
import laneNewSvg from '$lib/assets/empty-state/lane-new.svg?raw';
7-
import { invoke } from '$lib/backend/ipc';
7+
import { CLI_MANAGER } from '$lib/cli/cli';
88
import { SETTINGS_SERVICE } from '$lib/config/appSettingsV2';
99
import { projectAiGenEnabled } from '$lib/config/config';
1010
import { FEED_FACTORY } from '$lib/feed/feed';
@@ -26,6 +26,9 @@
2626
const settingsService = inject(SETTINGS_SERVICE);
2727
const settingsStore = $derived(settingsService.appSettings);
2828
29+
const cliManager = inject(CLI_MANAGER);
30+
const [instalCLI, installingCLI] = cliManager.install;
31+
2932
const combinedEntries = $derived(feed.combined);
3033
const lastAddedId = $derived(feed.lastAddedId);
3134
@@ -202,7 +205,8 @@
202205
kind="outline"
203206
icon="play"
204207
size="tag"
205-
onclick={async () => await invoke('install_cli')}>Install But CLI</Button
208+
loading={installingCLI.current.isLoading}
209+
onclick={async () => await instalCLI()}>Install But CLI</Button
206210
>
207211
<span class="clr-text-2">(requires admin)</span>
208212
or

apps/desktop/src/components/FileContextMenu.svelte

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import { writeClipboard } from '$lib/backend/clipboard';
77
import { changesToDiffSpec } from '$lib/commits/utils';
88
import { projectAiExperimentalFeaturesEnabled, projectAiGenEnabled } from '$lib/config/config';
9+
import { FILE_SERVICE } from '$lib/files/fileService';
910
import { isTreeChange, type TreeChange } from '$lib/hunks/change';
1011
import { platformName } from '$lib/platform/platform';
1112
import { vscodePath } from '$lib/project/project';
@@ -15,7 +16,7 @@
1516
import { STACK_SERVICE } from '$lib/stacks/stackService.svelte';
1617
import { UI_STATE } from '$lib/state/uiState.svelte';
1718
import { computeChangeStatus } from '$lib/utils/fileStatus';
18-
import { getEditorUri, openExternalUrl, showFileInFolder } from '$lib/utils/url';
19+
import { getEditorUri, openExternalUrl } from '$lib/utils/url';
1920
import { inject } from '@gitbutler/shared/context';
2021
2122
import {
@@ -61,6 +62,7 @@
6162
const idSelection = inject(ID_SELECTION);
6263
const aiService = inject(AI_SERVICE);
6364
const actionService = inject(ACTION_SERVICE);
65+
const fileService = inject(FILE_SERVICE);
6466
const [autoCommit, autoCommitting] = actionService.autoCommit;
6567
const [branchChanges, branchingChanges] = actionService.branchChanges;
6668
const [absorbChanges, absorbingChanges] = actionService.absorb;
@@ -441,7 +443,7 @@
441443
const projectPath = project?.path;
442444
if (projectPath) {
443445
const absPath = await join(projectPath, item.changes[0]!.path);
444-
await showFileInFolder(absPath);
446+
await fileService.showFileInFolder(absPath);
445447
}
446448
contextMenu.close();
447449
}}

apps/desktop/src/components/ProjectSettingsMenuAction.svelte

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
<script lang="ts">
22
import { goto } from '$app/navigation';
3+
import { FILE_SERVICE } from '$lib/files/fileService';
34
import { vscodePath } from '$lib/project/project';
45
import { PROJECTS_SERVICE } from '$lib/project/projectsService';
56
import { newProjectSettingsPath } from '$lib/routes/routes.svelte';
67
import { historyPath } from '$lib/routes/routes.svelte';
78
import { SETTINGS } from '$lib/settings/userSettings';
89
import { SHORTCUT_SERVICE } from '$lib/shortcuts/shortcutService';
9-
import { getEditorUri, openExternalUrl, showFileInFolder } from '$lib/utils/url';
10+
import { getEditorUri, openExternalUrl } from '$lib/utils/url';
1011
import { inject } from '@gitbutler/shared/context';
1112
import { mergeUnlisten } from '@gitbutler/ui/utils/mergeUnlisten';
1213
@@ -16,6 +17,7 @@
1617
1718
const userSettings = inject(SETTINGS);
1819
const shortcutService = inject(SHORTCUT_SERVICE);
20+
const fileService = inject(FILE_SERVICE);
1921
2022
$effect(() =>
2123
mergeUnlisten(
@@ -44,7 +46,7 @@
4446
throw new Error(`Project not found: ${projectId}`);
4547
}
4648
// Show the project directory in the default file manager (cross-platform)
47-
await showFileInFolder(project.path);
49+
await fileService.showFileInFolder(project.path);
4850
})
4951
)
5052
);

apps/desktop/src/components/ShareIssueModal.svelte

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
<script lang="ts">
22
import { page } from '$app/stores';
3-
import { invoke } from '$lib/backend/ipc';
3+
import { FILE_SERVICE } from '$lib/files/fileService';
4+
import { GIT_SERVICE } from '$lib/git/gitService';
45
import { SHORTCUT_SERVICE } from '$lib/shortcuts/shortcutService';
5-
import * as zip from '$lib/support/dataSharing';
6+
import { DATA_SHARING_SERVICE } from '$lib/support/dataSharing';
67
import { USER } from '$lib/user/user';
78
import { inject } from '@gitbutler/shared/context';
89
import { HTTP_CLIENT } from '@gitbutler/shared/network/httpClient';
@@ -21,16 +22,17 @@
2122
2223
const shortcutService = inject(SHORTCUT_SERVICE);
2324
const httpClient = inject(HTTP_CLIENT);
25+
const fileService = inject(FILE_SERVICE);
26+
const dataSharingService = inject(DATA_SHARING_SERVICE);
27+
const gitService = inject(GIT_SERVICE);
2428
const user = inject(USER);
2529
2630
export function show() {
2731
modal?.show();
2832
}
2933
3034
async function gitIndexLength() {
31-
return await invoke<void>('git_index_size', {
32-
projectId: projectId
33-
});
35+
return await gitService.indexSize(projectId);
3436
}
3537
3638
let modal: ReturnType<typeof Modal> | undefined = $state();
@@ -49,9 +51,8 @@
4951
}
5052
5153
async function readZipFile(path: string, filename?: string): Promise<File | Blob> {
52-
const { readFile } = await import('@tauri-apps/plugin-fs');
5354
// Using `new Uint8Array` to get an `ArrayBuffer` rather than `ArrayBufferLike`.
54-
const file = new Uint8Array(await readFile(path));
55+
const file = new Uint8Array(await fileService.readFile(path));
5556
const fileName = filename ?? path.split('/').pop();
5657
return fileName
5758
? new File([file], fileName, { type: 'application/zip' })
@@ -73,10 +74,12 @@
7374
7475
chipToasts.promise(
7576
Promise.all([
76-
sendLogs ? zip.logs().then(async (path) => await readZipFile(path, 'logs.zip')) : undefined,
77+
sendLogs
78+
? dataSharingService.logs().then(async (path) => await readZipFile(path, 'logs.zip'))
79+
: undefined,
7780
sendProjectRepository
78-
? zip
79-
.projectData({ projectId })
81+
? dataSharingService
82+
.projectData(projectId)
8083
.then(async (path) => await readZipFile(path, 'project.zip'))
8184
: undefined
8285
]).then(

apps/desktop/src/components/profileSettings/CliSymLink.svelte

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<script lang="ts">
2-
import { invoke } from '$lib/backend/ipc';
2+
import { CLI_MANAGER } from '$lib/cli/cli';
33
import { copyToClipboard } from '@gitbutler/shared/clipboard';
4+
import { inject } from '@gitbutler/shared/context';
45
import { Icon } from '@gitbutler/ui';
56
67
interface Props {
@@ -9,20 +10,23 @@
910
1011
const { class: classes = '' }: Props = $props();
1112
12-
async function cli_command(): Promise<string> {
13-
const path: string = await invoke('cli_path');
13+
const cliManager = inject(CLI_MANAGER);
14+
const cliPath = cliManager.path();
15+
16+
function cliCommand(path: string): string {
1417
const command = "sudo ln -sf '" + path + "' /usr/local/bin/but";
1518
return command;
1619
}
1720
</script>
1821

1922
<div class="symlink-copy-box {classes}">
20-
{#await cli_command() then command}
23+
{#if cliPath.current?.data}
24+
{@const command = cliCommand(cliPath.current.data)}
2125
<p>{command}</p>
2226
<button type="button" class="symlink-copy-icon" onclick={() => copyToClipboard(command)}>
2327
<Icon name="copy" />
2428
</button>
25-
{/await}
29+
{/if}
2630
</div>
2731

2832
<style lang="postcss">

apps/desktop/src/components/profileSettings/GeneralSettings.svelte

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import Login from '$components/Login.svelte';
44
import WelcomeSigninAction from '$components/WelcomeSigninAction.svelte';
55
import CliSymLink from '$components/profileSettings/CliSymLink.svelte';
6-
import { invoke } from '$lib/backend/ipc';
6+
import { CLI_MANAGER } from '$lib/cli/cli';
77
import { SETTINGS_SERVICE } from '$lib/config/appSettingsV2';
88
import { showError } from '$lib/notifications/toasts';
99
import { PROJECTS_SERVICE } from '$lib/project/projectsService';
@@ -34,6 +34,9 @@
3434
const updaterService = inject(UPDATER_SERVICE);
3535
const disableAutoChecks = updaterService.disableAutoChecks;
3636
37+
const cliManager = inject(CLI_MANAGER);
38+
const [instalCLI, installingCLI] = cliManager.install;
39+
3740
const fileTypes = ['image/jpeg', 'image/png'];
3841
3942
let saving = $state(false);
@@ -235,7 +238,12 @@
235238

236239
<div class="flex flex-col gap-16">
237240
<div class="flex gap-8 justify-end">
238-
<Button style="pop" icon="play" onclick={async () => await invoke('install_cli')}
241+
<Button
242+
style="pop"
243+
icon="play"
244+
onclick={async () => await instalCLI()}
245+
loading={installingCLI.current.isLoading}
246+
>
239247
>Install But CLI</Button
240248
>
241249
<Button

apps/desktop/src/lib/ai/service.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121
type AIClient,
2222
type Prompt
2323
} from '$lib/ai/types';
24-
import { Tauri } from '$lib/backend/tauri';
24+
import createBackend from '$lib/backend';
2525
import { type GbConfig, GitConfigService } from '$lib/config/gitConfigService';
2626
import { TokenMemoryService } from '$lib/stores/tokenMemoryService';
2727
import { HttpClient } from '@gitbutler/shared/network/httpClient';
@@ -43,7 +43,8 @@ const defaultSecretsConfig = Object.freeze({
4343

4444
class DummyGitConfigService extends GitConfigService {
4545
constructor(private config: { [index: string]: string | undefined }) {
46-
super(new Tauri());
46+
const backend = createBackend();
47+
super(backend);
4748
}
4849
async getGbConfig(_projectId: string): Promise<GbConfig> {
4950
throw new Error('Method not implemented.');

0 commit comments

Comments
 (0)