mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-02 07:53:55 +03:00
add delete all data
This commit is contained in:
parent
b3aff720df
commit
ed3ed7e84b
@ -500,4 +500,12 @@ impl App {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn delete_all_data(&self) -> Result<()> {
|
||||
self.deltas_searcher.delete_all_data().context("failed to delete search data")?;
|
||||
for project in self.list_projects()? {
|
||||
self.delete_project(&project.id).context("failed to delete project")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,17 @@ impl MetaStorage {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete_all(&self) -> Result<()> {
|
||||
let filepath = self
|
||||
.storage
|
||||
.local_data_dir()
|
||||
.join("indexes")
|
||||
.join(format!("v{}", CURRENT_VERSION))
|
||||
.join("meta");
|
||||
fs::remove_dir_all(filepath)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get(&self, project_id: &str, session_hash: &str) -> Result<Option<u64>> {
|
||||
let filepath = Path::new("indexes")
|
||||
.join(format!("v{}", CURRENT_VERSION))
|
||||
@ -130,6 +141,18 @@ impl Deltas {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn delete_all_data(&self) -> Result<()> {
|
||||
self.meta_storage
|
||||
.delete_all()
|
||||
.context("Could not delete meta data")?;
|
||||
let mut writer = self.writer.lock().unwrap();
|
||||
writer
|
||||
.delete_all_documents()
|
||||
.context("Could not delete all documents")?;
|
||||
writer.commit().context("Could not commit")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn index_session(
|
||||
&self,
|
||||
repository: &app::gb_repository::Repository,
|
||||
|
@ -429,6 +429,14 @@ async fn git_commit(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[timed(duration(printer = "debug!"))]
|
||||
#[tauri::command(async)]
|
||||
async fn delete_all_data(handle: tauri::AppHandle) -> Result<(), Error> {
|
||||
let app = handle.state::<app::App>();
|
||||
app.delete_all_data().context("failed to delete all data")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let tauri_context = generate_context!();
|
||||
|
||||
@ -560,6 +568,7 @@ fn main() {
|
||||
git_stage,
|
||||
git_unstage,
|
||||
git_wd_diff,
|
||||
delete_all_data,
|
||||
])
|
||||
.build(tauri_context)
|
||||
.expect("Failed to build tauri app")
|
||||
|
@ -16,6 +16,10 @@ impl Storage {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn local_data_dir(&self) -> &Path {
|
||||
&self.local_data_dir
|
||||
}
|
||||
|
||||
pub fn read<P: AsRef<Path>>(&self, path: P) -> Result<Option<String>> {
|
||||
let file_path = self.local_data_dir.join(path);
|
||||
if !file_path.exists() {
|
||||
|
@ -10,3 +10,7 @@ export type { Project } from './projects';
|
||||
export * as searchResults from './search';
|
||||
export { type SearchResult } from './search';
|
||||
export * as files from './files';
|
||||
|
||||
import { invoke } from '$lib/ipc';
|
||||
|
||||
export const deleteAllData = () => invoke<void>('delete_all_data');
|
||||
|
@ -1,7 +1,9 @@
|
||||
<script lang="ts">
|
||||
import type { LoginToken, CloudApi, users } from '$lib/api';
|
||||
import { toasts, log } from '$lib';
|
||||
import { derived, writable } from '@square/svelte-store';
|
||||
import { open } from '@tauri-apps/api/shell';
|
||||
import Button from './Button';
|
||||
|
||||
export let user: Awaited<ReturnType<typeof users.CurrentUser>>;
|
||||
export let api: Awaited<ReturnType<typeof CloudApi>>;
|
||||
@ -19,15 +21,25 @@
|
||||
});
|
||||
};
|
||||
|
||||
let signUpOrLoginLoading = false;
|
||||
const onSignUpOrLoginClick = () => {
|
||||
Promise.resolve()
|
||||
.then(() => (signUpOrLoginLoading = true))
|
||||
.then(api.login.token.create)
|
||||
.then(token.set)
|
||||
.catch((e) => {
|
||||
log.error(e);
|
||||
toasts.error('Something went wrong');
|
||||
})
|
||||
.finally(() => (signUpOrLoginLoading = false));
|
||||
};
|
||||
const token = writable<LoginToken | null>(null);
|
||||
const authUrl = derived(token, ($token) => $token?.url as string);
|
||||
</script>
|
||||
|
||||
<div>
|
||||
{#if $user}
|
||||
<button class="text-zinc-400 hover:text-red-400 hover:underline" on:click={() => user.delete()}
|
||||
>Log out</button
|
||||
>
|
||||
<Button kind="plain" color="destructive" on:click={user.delete}>Log out</Button>
|
||||
{:else if $token !== null}
|
||||
{#await Promise.all([open($token.url), pollForUser($token.token)])}
|
||||
<div>Log in in your system browser</div>
|
||||
@ -37,9 +49,8 @@
|
||||
if you are not redirected automatically, you can
|
||||
</p>
|
||||
{:else}
|
||||
<button
|
||||
class="rounded bg-blue-400 py-1 px-3 text-white"
|
||||
on:click={() => api.login.token.create().then(token.set)}>Sign up or Log in</button
|
||||
>
|
||||
<Button loading={signUpOrLoginLoading} color="primary" on:click={onSignUpOrLoginClick}>
|
||||
Sign up or Log in
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
export let data: LayoutData;
|
||||
const { user, posthog, projects, sentry, events, hotkeys } = data;
|
||||
$: console.log($user);
|
||||
|
||||
const project = derived([page, projects], ([page, projects]) =>
|
||||
projects?.find((project) => project.id === page.params.projectId)
|
||||
@ -66,7 +67,7 @@
|
||||
<div class="mr-6">
|
||||
<Link href="/users/">
|
||||
{#await user.load() then}
|
||||
{#if $user}
|
||||
{#if $user !== null}
|
||||
{#if $user.picture}
|
||||
<img class="inline-block h-5 w-5 rounded-full" src={$user.picture} alt="Avatar" />
|
||||
{/if}
|
||||
|
@ -1,7 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { Button, Login } from '$lib/components';
|
||||
import { Button, Dialog, Login } from '$lib/components';
|
||||
import type { PageData } from './$types';
|
||||
import { log, toasts } from '$lib';
|
||||
import { deleteAllData } from '$lib/api';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
export let data: PageData;
|
||||
const { user, api } = data;
|
||||
@ -61,179 +63,207 @@
|
||||
pictureChanged = false;
|
||||
saving = false;
|
||||
};
|
||||
|
||||
let isDeleting = false;
|
||||
let deleteConfirmationDialog: Dialog;
|
||||
|
||||
const onDeleteClicked = () =>
|
||||
Promise.resolve()
|
||||
.then(() => (isDeleting = true))
|
||||
.then(() => deleteAllData())
|
||||
.then(() => user.delete())
|
||||
.then(() => toasts.success('All data deleted'))
|
||||
.catch((e) => {
|
||||
log.error(e);
|
||||
toasts.error('Failed to delete project');
|
||||
})
|
||||
.then(() => deleteConfirmationDialog.close())
|
||||
.then(() => goto('/', { replaceState: true, invalidateAll: true }))
|
||||
.finally(() => (isDeleting = false));
|
||||
</script>
|
||||
|
||||
<div class="mx-auto p-4">
|
||||
<div class="mx-auto max-w-xl p-4">
|
||||
{#if $user}
|
||||
<div class="flex flex-col gap-6 text-zinc-100">
|
||||
<header class="flex items-center justify-between">
|
||||
<div class="flex flex-col">
|
||||
<h2 class="text-2xl font-medium">GitButler Cloud Account</h2>
|
||||
<div class="">Your online account details on gitbutler.com</div>
|
||||
<div class="mx-auto max-w-xl p-8">
|
||||
{#if $user}
|
||||
<div class="flex flex-col gap-6 text-zinc-100">
|
||||
<header class="flex items-center justify-between">
|
||||
<div class="flex flex-col">
|
||||
<h2 class="text-2xl font-medium">GitButler Cloud Account</h2>
|
||||
<div class="">Your online account details on gitbutler.com</div>
|
||||
</div>
|
||||
<Login {user} {api} />
|
||||
</header>
|
||||
|
||||
<form
|
||||
on:submit={onSubmit}
|
||||
class="user-form flex flex-row items-start justify-between gap-12 rounded-lg py-2"
|
||||
>
|
||||
<fields id="right" class="flex flex-col items-center gap-2 pt-6">
|
||||
{#if $user.picture}
|
||||
<img
|
||||
class="h-28 w-28 rounded-full border-zinc-300"
|
||||
src={userPicture}
|
||||
alt="Your avatar"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<label
|
||||
title="Edit profile photo"
|
||||
for="picture"
|
||||
class="font-sm -mt-6 -ml-16 cursor-default rounded-lg border border-zinc-600 bg-zinc-800 px-2 text-center text-zinc-300 hover:bg-zinc-900 hover:text-zinc-50"
|
||||
>
|
||||
Edit
|
||||
<input
|
||||
on:change={onPictureChange}
|
||||
type="file"
|
||||
id="picture"
|
||||
name="picture"
|
||||
accept={fileTypes.join('')}
|
||||
class="hidden"
|
||||
/>
|
||||
</label>
|
||||
</fields>
|
||||
|
||||
<fields id="left" class="flex flex-1 flex-col gap-3">
|
||||
<div class="flex flex-col gap-1">
|
||||
<label for="name" class="text-zinc-400">Name</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
spellcheck="false"
|
||||
id="name"
|
||||
name="name"
|
||||
bind:value={userNameInput}
|
||||
type="text"
|
||||
class="w-full rounded border border-zinc-600 bg-zinc-700 px-4 py-2 text-zinc-300"
|
||||
placeholder="Name can't be empty"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<Login {user} {api} />
|
||||
</header>
|
||||
|
||||
<form
|
||||
on:submit={onSubmit}
|
||||
class="user-form flex flex-row items-start justify-between gap-12 rounded-lg py-2"
|
||||
>
|
||||
<fields id="right" class="flex flex-col items-center gap-2 pt-6">
|
||||
{#if $user.picture}
|
||||
<img
|
||||
class="h-28 w-28 rounded-full border-zinc-300"
|
||||
src={userPicture}
|
||||
alt="Your avatar"
|
||||
/>
|
||||
{/if}
|
||||
<div class="flex flex-col gap-1">
|
||||
<label for="email" class="text-zinc-400">Email</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
spellcheck="false"
|
||||
disabled
|
||||
id="email"
|
||||
name="email"
|
||||
bind:value={$user.email}
|
||||
type="text"
|
||||
class="w-full rounded border border-zinc-600 bg-zinc-700 px-4 py-2 text-zinc-300"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<label
|
||||
title="Edit profile photo"
|
||||
for="picture"
|
||||
class="font-sm -mt-6 -ml-16 cursor-default rounded-lg border border-zinc-600 bg-zinc-800 px-2 text-center text-zinc-300 hover:bg-zinc-900 hover:text-zinc-50"
|
||||
>
|
||||
Edit
|
||||
<input
|
||||
on:change={onPictureChange}
|
||||
type="file"
|
||||
id="picture"
|
||||
name="picture"
|
||||
accept={fileTypes.join('')}
|
||||
class="hidden"
|
||||
/>
|
||||
</label>
|
||||
</fields>
|
||||
<footer class="flex justify-end pt-4">
|
||||
<Button disabled={!canTriggerUpdate} loading={saving} color="primary" type="submit">
|
||||
Update profile
|
||||
</Button>
|
||||
</footer>
|
||||
</fields>
|
||||
</form>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex flex-col items-center justify-items-center space-y-6 text-white">
|
||||
<div class="text-4xl font-bold text-white">Connect to GitButler Cloud</div>
|
||||
<div>Sign up or log in to GitButler Cloud for more tools and features:</div>
|
||||
<ul class="space-y-2 pb-4 text-zinc-400">
|
||||
<li class="flex flex-row space-x-3">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="white"
|
||||
class="h-6 w-6"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M12 16.5V9.75m0 0l3 3m-3-3l-3 3M6.75 19.5a4.5 4.5 0 01-1.41-8.775 5.25 5.25 0 0110.233-2.33 3 3 0 013.758 3.848A3.752 3.752 0 0118 19.5H6.75z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Backup everything you do in any of your projects</span>
|
||||
</li>
|
||||
<li class="flex flex-row space-x-3">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="white"
|
||||
class="h-6 w-6"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M7.5 21L3 16.5m0 0L7.5 12M3 16.5h13.5m0-13.5L21 7.5m0 0L16.5 12M21 7.5H7.5"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<fields id="left" class="flex flex-1 flex-col gap-3">
|
||||
<div class="flex flex-col gap-1">
|
||||
<label for="name" class="text-zinc-400">Name</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
spellcheck="false"
|
||||
id="name"
|
||||
name="name"
|
||||
bind:value={userNameInput}
|
||||
type="text"
|
||||
class="w-full rounded border border-zinc-600 bg-zinc-700 px-4 py-2 text-zinc-300"
|
||||
placeholder="Name can't be empty"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-1">
|
||||
<label for="email" class="text-zinc-400">Email</label>
|
||||
<input
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
spellcheck="false"
|
||||
disabled
|
||||
id="email"
|
||||
name="email"
|
||||
bind:value={$user.email}
|
||||
type="text"
|
||||
class="w-full rounded border border-zinc-600 bg-zinc-700 px-4 py-2 text-zinc-300"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<footer class="flex justify-end pt-4">
|
||||
<Button disabled={!canTriggerUpdate} loading={saving} color="primary" type="submit">
|
||||
Update profile
|
||||
</Button>
|
||||
</footer>
|
||||
</fields>
|
||||
</form>
|
||||
<span>Sync your data across devices</span>
|
||||
</li>
|
||||
<li class="flex flex-row space-x-3">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="white"
|
||||
class="h-6 w-6"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10"
|
||||
/>
|
||||
</svg>
|
||||
<span>AI commit message automated suggestions</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="mt-8 text-center">
|
||||
<Login {user} {api} />
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex flex-col items-center justify-items-center space-y-6 text-white">
|
||||
<div class="text-4xl font-bold text-white">Connect to GitButler Cloud</div>
|
||||
<div>Sign up or log in to GitButler Cloud for more tools and features:</div>
|
||||
<ul class="space-y-2 pb-4 text-zinc-400">
|
||||
<li class="flex flex-row space-x-3">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="white"
|
||||
class="h-6 w-6"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M12 16.5V9.75m0 0l3 3m-3-3l-3 3M6.75 19.5a4.5 4.5 0 01-1.41-8.775 5.25 5.25 0 0110.233-2.33 3 3 0 013.758 3.848A3.752 3.752 0 0118 19.5H6.75z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Backup everything you do in any of your projects</span>
|
||||
</li>
|
||||
<li class="flex flex-row space-x-3">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="white"
|
||||
class="h-6 w-6"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M7.5 21L3 16.5m0 0L7.5 12M3 16.5h13.5m0-13.5L21 7.5m0 0L16.5 12M21 7.5H7.5"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<span>Sync your data across devices</span>
|
||||
</li>
|
||||
<li class="flex flex-row space-x-3">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="white"
|
||||
class="h-6 w-6"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10"
|
||||
/>
|
||||
</svg>
|
||||
<span>AI commit message automated suggestions</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="mt-8 text-center">
|
||||
<Login {user} {api} />
|
||||
</div>
|
||||
<div class="text-center text-zinc-300">
|
||||
You will still need to give us permission for each project before we transfer any data to
|
||||
our servers. You can revoke this permission at any time.
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="mt-8 flex flex-col border-t border-zinc-400 pt-4">
|
||||
<div class="mt-4">
|
||||
<a
|
||||
class="flex flex-col gap-2 rounded border border-zinc-700 bg-card-default p-3 text-zinc-400 shadow transition duration-150 ease-out hover:bg-card-active hover:ease-in"
|
||||
href="mailto:hello@gitbutler.com?subject=Feedback or question!"
|
||||
>
|
||||
<h2 class="text-lg text-zinc-300">Get Support</h2>
|
||||
<div class="text-zinc-500">If you have an issue or any questions, please email us.</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<a
|
||||
class="flex flex-col gap-2 rounded border border-zinc-700 bg-card-default p-3 text-zinc-400 shadow transition duration-150 ease-out hover:bg-card-active hover:ease-in"
|
||||
href="https://discord.gg/wDKZCPEjXC"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<h2 class="text-lg text-zinc-300">Join our Discord</h2>
|
||||
<div class="text-zinc-500">Share feedback, request, or ask questions</div>
|
||||
</a>
|
||||
<div class="text-center text-zinc-300">
|
||||
You will still need to give us permission for each project before we transfer any data to
|
||||
our servers. You can revoke this permission at any time.
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="mt-8 flex flex-col gap-4 border-t border-zinc-400 pt-4">
|
||||
<a
|
||||
class="flex flex-col gap-2 rounded border border-zinc-700 bg-card-default p-3 text-zinc-400 shadow transition duration-150 ease-out hover:bg-card-active hover:ease-in"
|
||||
href="mailto:hello@gitbutler.com?subject=Feedback or question!"
|
||||
>
|
||||
<h2 class="text-lg text-zinc-300">Get Support</h2>
|
||||
<div class="text-zinc-500">If you have an issue or any questions, please email us.</div>
|
||||
</a>
|
||||
<a
|
||||
class="flex flex-col gap-2 rounded border border-zinc-700 bg-card-default p-3 text-zinc-400 shadow transition duration-150 ease-out hover:bg-card-active hover:ease-in"
|
||||
href="https://discord.gg/wDKZCPEjXC"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<h2 class="text-lg text-zinc-300">Join our Discord</h2>
|
||||
<div class="text-zinc-500">Share feedback, request, or ask questions</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="mt-8 flex flex-col gap-4 border-t border-zinc-400 pt-4">
|
||||
<Button color="destructive" kind="outlined" on:click={() => deleteConfirmationDialog.show()}>
|
||||
Delete all data
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Dialog bind:this={deleteConfirmationDialog}>
|
||||
<svelte:fragment slot="title">Delete all local data?</svelte:fragment>
|
||||
|
||||
<p>Are you sure you want to delete all local data? This can’t be undone.</p>
|
||||
|
||||
<svelte:fragment slot="controls" let:close>
|
||||
<Button kind="outlined" on:click={close}>Cancel</Button>
|
||||
<Button color="destructive" loading={isDeleting} on:click={onDeleteClicked}>Delete</Button>
|
||||
</svelte:fragment>
|
||||
</Dialog>
|
||||
|
Loading…
Reference in New Issue
Block a user