mirror of
https://github.com/ankitects/anki.git
synced 2025-11-06 12:47:11 -05:00
extract normal state component out of Start
This commit is contained in:
parent
7b5afb8dd8
commit
1ce305620d
2 changed files with 169 additions and 110 deletions
160
qt/launcher-gui/src/routes/Normal.svelte
Normal file
160
qt/launcher-gui/src/routes/Normal.svelte
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
<!--
|
||||
Copyright: Ankitects Pty Ltd and contributors
|
||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
import {
|
||||
Mirror,
|
||||
type Options as OptionsProto,
|
||||
type ChooseVersionResponse,
|
||||
type GetMirrorsResponse_Pair,
|
||||
} from "@generated/anki/launcher_pb";
|
||||
import {
|
||||
chooseVersion,
|
||||
getAvailableVersions,
|
||||
getExistingVersions,
|
||||
} from "@generated/backend-launcher";
|
||||
import Row from "$lib/components/Row.svelte";
|
||||
import { tr } from "./stores";
|
||||
import Warning from "./Warning.svelte";
|
||||
import Action from "./Action.svelte";
|
||||
import Spinner from "./Spinner.svelte";
|
||||
import Options from "./Options.svelte";
|
||||
import Term from "./Term.svelte";
|
||||
import AnkiWillStart from "./AnkiWillStart.svelte";
|
||||
import type { Terminal } from "@xterm/xterm";
|
||||
|
||||
let {
|
||||
options,
|
||||
mirrors,
|
||||
uninstall,
|
||||
footer = $bindable(),
|
||||
}: {
|
||||
options: OptionsProto;
|
||||
mirrors: GetMirrorsResponse_Pair[];
|
||||
uninstall: (() => void) | null;
|
||||
footer: any; // https://github.com/sveltejs/svelte/issues/15182
|
||||
} = $props();
|
||||
|
||||
footer = _footer;
|
||||
|
||||
let releasesPromise = $state(getAvailableVersions({}, { alertOnError: false }));
|
||||
let existingPromise = $state(getExistingVersions({}, { alertOnError: false }));
|
||||
let loadPromise = $derived(Promise.all([releasesPromise, existingPromise]));
|
||||
|
||||
let allowBetas = $state(options.allowBetas);
|
||||
let downloadCaching = $state(options.downloadCaching);
|
||||
let selectedMirror = $state(Mirror.DISABLED);
|
||||
|
||||
let choosePromise: Promise<ChooseVersionResponse | null> = $state(
|
||||
Promise.resolve(null),
|
||||
);
|
||||
|
||||
let error: Error | null = $state(null);
|
||||
const setError = (e: Error) => {
|
||||
error = e;
|
||||
};
|
||||
|
||||
let term: Terminal | undefined = $state(undefined);
|
||||
let termOpen = $state(false);
|
||||
let chosen = $state(false);
|
||||
|
||||
const choose = (version: string, keepExisting: boolean, current?: string) => {
|
||||
chosen = true;
|
||||
term?.reset();
|
||||
choosePromise = chooseVersion({
|
||||
version,
|
||||
keepExisting,
|
||||
options: { allowBetas, downloadCaching, mirror: selectedMirror },
|
||||
...(current ? { current } : {}),
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
{#await choosePromise}
|
||||
<Row class="centre m-3">
|
||||
<Spinner label={$tr.launcherSyncing()} />
|
||||
</Row>
|
||||
{:then res}
|
||||
{#if res === null}
|
||||
{#await loadPromise}
|
||||
<Row class="centre m-3">
|
||||
<Spinner label={$tr.launcherLoadingVersions()} />
|
||||
</Row>
|
||||
{:then [releases, existing]}
|
||||
<Action {releases} {existing} {allowBetas} {choose} {uninstall} />
|
||||
{:catch e}
|
||||
{setError(e)}
|
||||
<Warning
|
||||
warning={$tr.lauuncherFailedToLoadVersions()}
|
||||
className="alert-danger"
|
||||
/>
|
||||
{/await}
|
||||
{:else}
|
||||
<Row class="centre m-3">
|
||||
<AnkiWillStart {res} />
|
||||
</Row>
|
||||
{/if}
|
||||
{:catch e}
|
||||
{setError(e)}
|
||||
<Warning warning={$tr.launcherFailedToSync()} className="alert-danger" />
|
||||
{/await}
|
||||
{#if error != null}
|
||||
<Row>
|
||||
<pre>{error.message}</pre>
|
||||
</Row>
|
||||
{/if}
|
||||
|
||||
{#snippet _footer()}
|
||||
<Term bind:term bind:open={termOpen} />
|
||||
{#if !chosen}
|
||||
<Row class="row-columns">
|
||||
<Options
|
||||
{mirrors}
|
||||
bind:allowBetas
|
||||
bind:downloadCaching
|
||||
bind:selectedMirror
|
||||
/>
|
||||
</Row>
|
||||
{/if}
|
||||
{/snippet}
|
||||
|
||||
<style lang="scss">
|
||||
:root {
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
|
||||
text-rendering: optimizeLegibility;
|
||||
font-synthesis: none;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
.logo {
|
||||
max-width: 50px;
|
||||
margin-inline-end: 1em;
|
||||
|
||||
-webkit-user-drag: none;
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
|
||||
.title {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
:global(.centre) {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
pre {
|
||||
white-space: pre-wrap; /* Since CSS 2.1 */
|
||||
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
||||
white-space: -pre-wrap; /* Opera 4-6 */
|
||||
white-space: -o-pre-wrap; /* Opera 7 */
|
||||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||
}
|
||||
</style>
|
||||
|
|
@ -3,79 +3,29 @@ Copyright: Ankitects Pty Ltd and contributors
|
|||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
-->
|
||||
<script lang="ts">
|
||||
import {
|
||||
Mirror,
|
||||
type Options as OptionsProto,
|
||||
type ChooseVersionResponse,
|
||||
type GetLangsResponse_Pair,
|
||||
type GetMirrorsResponse_Pair,
|
||||
} from "@generated/anki/launcher_pb";
|
||||
import {
|
||||
chooseVersion,
|
||||
getAvailableVersions,
|
||||
getExistingVersions,
|
||||
} from "@generated/backend-launcher";
|
||||
import { type GetLangsResponse_Pair } from "@generated/anki/launcher_pb";
|
||||
import Row from "$lib/components/Row.svelte";
|
||||
import EnumSelectorRow from "$lib/components/EnumSelectorRow.svelte";
|
||||
import SettingTitle from "$lib/components/SettingTitle.svelte";
|
||||
import TitledContainer from "$lib/components/TitledContainer.svelte";
|
||||
import Container from "$lib/components/Container.svelte";
|
||||
import { tr } from "./stores";
|
||||
import Warning from "./Warning.svelte";
|
||||
import Action from "./Action.svelte";
|
||||
import Spinner from "./Spinner.svelte";
|
||||
import Options from "./Options.svelte";
|
||||
import Term from "./Term.svelte";
|
||||
import AnkiWillStart from "./AnkiWillStart.svelte";
|
||||
import type { Terminal } from "@xterm/xterm";
|
||||
|
||||
let {
|
||||
langs,
|
||||
selectedLang = $bindable(),
|
||||
options,
|
||||
mirrors,
|
||||
children,
|
||||
footer,
|
||||
}: {
|
||||
langs: GetLangsResponse_Pair[];
|
||||
selectedLang: string;
|
||||
options: OptionsProto;
|
||||
mirrors: GetMirrorsResponse_Pair[];
|
||||
children: any;
|
||||
footer: any;
|
||||
} = $props();
|
||||
|
||||
let releasesPromise = $state(getAvailableVersions({}, { alertOnError: false }));
|
||||
let existingPromise = $state(getExistingVersions({}, { alertOnError: false }));
|
||||
let loadPromise = $derived(Promise.all([releasesPromise, existingPromise]));
|
||||
|
||||
const availableLangs = $derived(
|
||||
langs.map((p) => ({ label: p.name, value: p.locale })),
|
||||
);
|
||||
|
||||
let allowBetas = $state(options.allowBetas);
|
||||
let downloadCaching = $state(options.downloadCaching);
|
||||
let selectedMirror = $state(Mirror.DISABLED);
|
||||
|
||||
let choosePromise: Promise<ChooseVersionResponse | null> = $state(
|
||||
Promise.resolve(null),
|
||||
);
|
||||
|
||||
let error: Error | null = $state(null);
|
||||
const setError = (e: Error) => {
|
||||
error = e;
|
||||
};
|
||||
|
||||
let term: Terminal | undefined = $state(undefined);
|
||||
let termOpen = $state(false);
|
||||
let chosen = $state(false);
|
||||
|
||||
const choose = (version: string, keepExisting: boolean, current?: string) => {
|
||||
chosen = true;
|
||||
term?.reset();
|
||||
choosePromise = chooseVersion({
|
||||
version,
|
||||
keepExisting,
|
||||
options: { allowBetas, downloadCaching, mirror: selectedMirror },
|
||||
...(current ? { current } : {}),
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<Container
|
||||
|
|
@ -101,55 +51,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
{$tr.launcherLanguage()}
|
||||
</SettingTitle>
|
||||
</EnumSelectorRow>
|
||||
{#await choosePromise}
|
||||
<Row class="centre m-3">
|
||||
<Spinner label={$tr.launcherSyncing()} />
|
||||
</Row>
|
||||
{:then res}
|
||||
{#if res === null}
|
||||
{#await loadPromise}
|
||||
<Row class="centre m-3">
|
||||
<Spinner label={$tr.launcherLoadingVersions()} />
|
||||
</Row>
|
||||
{:then [releases, existing]}
|
||||
<Action {releases} {existing} {allowBetas} {choose} />
|
||||
{:catch e}
|
||||
{setError(e)}
|
||||
<Warning
|
||||
warning={$tr.lauuncherFailedToLoadVersions()}
|
||||
className="alert-danger"
|
||||
/>
|
||||
{/await}
|
||||
{:else}
|
||||
<Row class="centre m-3">
|
||||
<AnkiWillStart {res} />
|
||||
</Row>
|
||||
{/if}
|
||||
{:catch e}
|
||||
{setError(e)}
|
||||
<Warning
|
||||
warning={$tr.launcherFailedToSync()}
|
||||
className="alert-danger"
|
||||
/>
|
||||
{/await}
|
||||
{#if error != null}
|
||||
<Row>
|
||||
<pre>{error.message}</pre>
|
||||
</Row>
|
||||
{/if}
|
||||
|
||||
{@render children?.()}
|
||||
</TitledContainer>
|
||||
</Row>
|
||||
<Term bind:term bind:open={termOpen} />
|
||||
{#if !chosen}
|
||||
<Row class="row-columns">
|
||||
<Options
|
||||
{mirrors}
|
||||
bind:allowBetas
|
||||
bind:downloadCaching
|
||||
bind:selectedMirror
|
||||
/>
|
||||
</Row>
|
||||
{/if}
|
||||
|
||||
{@render footer?.()}
|
||||
</Container>
|
||||
|
||||
<style lang="scss">
|
||||
|
|
@ -182,12 +89,4 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|||
:global(.centre) {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
pre {
|
||||
white-space: pre-wrap; /* Since CSS 2.1 */
|
||||
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
||||
white-space: -pre-wrap; /* Opera 4-6 */
|
||||
white-space: -o-pre-wrap; /* Opera 7 */
|
||||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in a new issue