Various QOL changes
This commit is contained in:
@@ -10,7 +10,7 @@ type CropperModal = {
|
||||
|
||||
export const cropperStore = writable<CropperModal | undefined>(undefined);
|
||||
|
||||
export function showCropper(image: string, sentence: string) {
|
||||
export function showCropper(image: string, sentence?: string) {
|
||||
cropperStore.set({
|
||||
open: true,
|
||||
image,
|
||||
|
||||
@@ -64,7 +64,7 @@ export async function imageToWebp(source: File) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateLastCard(imageData: string | null | undefined, sentence: string) {
|
||||
export async function updateLastCard(imageData: string | null | undefined, sentence?: string) {
|
||||
const {
|
||||
overwriteImage,
|
||||
enabled,
|
||||
@@ -88,7 +88,7 @@ export async function updateLastCard(imageData: string | null | undefined, sente
|
||||
|
||||
const fields: Record<string, any> = {};
|
||||
|
||||
if (grabSentence) {
|
||||
if (grabSentence && sentence) {
|
||||
fields[sentenceField] = sentence;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { afterNavigate } from '$app/navigation';
|
||||
import { cropperStore, getCroppedImg, updateLastCard, type Pixels } from '$lib/anki-connect';
|
||||
import { settings } from '$lib/settings';
|
||||
import { Button, Modal, Spinner } from 'flowbite-svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import Cropper from 'svelte-easy-crop';
|
||||
@@ -43,7 +44,7 @@
|
||||
<Modal title="Crop image" bind:open on:{close}>
|
||||
{#if $cropperStore?.image && !loading}
|
||||
<div class=" flex flex-col gap-2">
|
||||
<div class="relative w-full h-[55svh] sm:h-[70svh]">
|
||||
<div class="relative w-full h-[55svh] sm:h-[65svh]">
|
||||
<Cropper
|
||||
zoomSpeed={0.5}
|
||||
maxZoom={10}
|
||||
@@ -51,6 +52,12 @@
|
||||
on:cropcomplete={onCropComplete}
|
||||
/>
|
||||
</div>
|
||||
{#if $settings.ankiConnectSettings.grabSentence && $cropperStore?.sentence}
|
||||
<p>
|
||||
<b>Sentence:</b>
|
||||
{$cropperStore?.sentence}
|
||||
</p>
|
||||
{/if}
|
||||
<Button on:click={onCrop}>Crop</Button>
|
||||
<Button on:click={close} outline color="light">Close</Button>
|
||||
</div>
|
||||
|
||||
74
src/lib/components/Reader/QuickActions.svelte
Normal file
74
src/lib/components/Reader/QuickActions.svelte
Normal file
@@ -0,0 +1,74 @@
|
||||
<script lang="ts">
|
||||
import { zoomFitToScreen } from '$lib/panzoom';
|
||||
import { SpeedDial, SpeedDialButton } from 'flowbite-svelte';
|
||||
import { settings } from '$lib/settings';
|
||||
import {
|
||||
ArrowLeftOutline,
|
||||
ArrowRightOutline,
|
||||
ImageOutline,
|
||||
ZoomOutOutline
|
||||
} from 'flowbite-svelte-icons';
|
||||
import { imageToWebp, showCropper, updateLastCard } from '$lib/anki-connect';
|
||||
import { promptConfirmation } from '$lib/util';
|
||||
|
||||
export let left: (_e: any, ingoreTimeOut?: boolean) => void;
|
||||
export let right: (_e: any, ingoreTimeOut?: boolean) => void;
|
||||
export let src: File;
|
||||
|
||||
let open = false;
|
||||
|
||||
function handleZoom() {
|
||||
zoomFitToScreen();
|
||||
open = false;
|
||||
}
|
||||
|
||||
function handleLeft(_e: Event) {
|
||||
left(_e, true);
|
||||
open = false;
|
||||
}
|
||||
|
||||
function handleRight(_e: Event) {
|
||||
right(_e, true);
|
||||
open = false;
|
||||
}
|
||||
|
||||
async function onUpdateCard() {
|
||||
if ($settings.ankiConnectSettings.enabled) {
|
||||
if ($settings.ankiConnectSettings.cropImage) {
|
||||
showCropper(URL.createObjectURL(src));
|
||||
} else {
|
||||
promptConfirmation('Add image to last created anki card?', async () => {
|
||||
const imageData = await imageToWebp(src);
|
||||
updateLastCard(imageData);
|
||||
});
|
||||
}
|
||||
}
|
||||
open = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if $settings.quickActions}
|
||||
<SpeedDial
|
||||
tooltip="none"
|
||||
trigger="click"
|
||||
defaultClass="absolute end-3 bottom-3 z-50"
|
||||
outline
|
||||
color="dark"
|
||||
bind:open
|
||||
>
|
||||
{#if $settings.ankiConnectSettings.enabled}
|
||||
<SpeedDialButton on:click={onUpdateCard}>
|
||||
<ImageOutline />
|
||||
</SpeedDialButton>
|
||||
{/if}
|
||||
<SpeedDialButton on:click={handleZoom}>
|
||||
<ZoomOutOutline />
|
||||
</SpeedDialButton>
|
||||
<SpeedDialButton on:click={handleRight}>
|
||||
<ArrowRightOutline />
|
||||
</SpeedDialButton>
|
||||
<SpeedDialButton on:click={handleLeft}>
|
||||
<ArrowLeftOutline />
|
||||
</SpeedDialButton>
|
||||
</SpeedDial>
|
||||
{/if}
|
||||
@@ -21,7 +21,7 @@
|
||||
import { page as pageStore } from '$app/stores';
|
||||
import SettingsButton from './SettingsButton.svelte';
|
||||
import { getCharCount } from '$lib/util/count-chars';
|
||||
import { afterUpdate } from 'svelte';
|
||||
import QuickActions from './QuickActions.svelte';
|
||||
|
||||
// TODO: Refactor this whole mess
|
||||
export let volumeSettings: VolumeSettings;
|
||||
@@ -196,7 +196,7 @@
|
||||
const { scale } = $panzoomStore.getTransform();
|
||||
|
||||
if (scale < 0.6) {
|
||||
$panzoomStore.zoomTo(clientX, clientY, 1.5);
|
||||
$panzoomStore.zoomTo(clientX, clientY, 1.4);
|
||||
} else {
|
||||
zoomFitToScreen();
|
||||
}
|
||||
@@ -213,8 +213,9 @@
|
||||
<svelte:head>
|
||||
<title>{volume?.mokuroData.volume || 'Volume'}</title>
|
||||
</svelte:head>
|
||||
<SettingsButton />
|
||||
{#if volume && pages}
|
||||
<QuickActions {left} {right} src={Object.values(volume?.files)[index]} />
|
||||
<SettingsButton />
|
||||
<Cropper />
|
||||
<Popover placement="bottom" trigger="click" triggeredBy="#page-num" class="z-20 w-full max-w-xs">
|
||||
<div class="flex flex-col gap-3">
|
||||
@@ -266,11 +267,13 @@
|
||||
<Panzoom>
|
||||
<button
|
||||
class="h-full fixed -left-full z-10 w-full hover:bg-slate-400 opacity-[0.01]"
|
||||
style:margin-left={`${$settings.edgeButtonWidth}px`}
|
||||
on:mousedown={mouseDown}
|
||||
on:mouseup={left}
|
||||
/>
|
||||
<button
|
||||
class="h-full fixed -right-full z-10 w-full hover:bg-slate-400 opacity-[0.01]"
|
||||
style:margin-right={`${$settings.edgeButtonWidth}px`}
|
||||
on:mousedown={mouseDown}
|
||||
on:mouseup={right}
|
||||
/>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import { toggleFullScreen } from '$lib/panzoom';
|
||||
import { isReader } from '$lib/util';
|
||||
|
||||
@@ -10,7 +8,6 @@
|
||||
{#if isReader()}
|
||||
<div class="flex flex-col gap-2">
|
||||
<Button color="alternative" on:click={toggleFullScreen}>Toggle fullscreen</Button>
|
||||
<Button color="alternative" on:click={() => goto(`/${$page.params.manga}`)}>Close reader</Button
|
||||
>
|
||||
<Button color="alternative" on:click={() => history.back()}>Close reader</Button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -4,9 +4,14 @@
|
||||
import ReaderToggles from './ReaderToggles.svelte';
|
||||
import { settings, updateSetting } from '$lib/settings';
|
||||
|
||||
let value = $settings.swipeThreshold;
|
||||
function onChange() {
|
||||
updateSetting('swipeThreshold', value);
|
||||
let swipeThresholdValue = $settings.swipeThreshold;
|
||||
let edgeButtonWidthValue = $settings.edgeButtonWidth;
|
||||
function onSwipeChange() {
|
||||
updateSetting('swipeThreshold', swipeThresholdValue);
|
||||
}
|
||||
|
||||
function onWidthChange() {
|
||||
updateSetting('edgeButtonWidth', edgeButtonWidthValue);
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -18,7 +23,17 @@
|
||||
<ReaderToggles />
|
||||
<div>
|
||||
<Label>Swipe threshold</Label>
|
||||
<Range on:change={onChange} min={20} max={90} disabled={!$settings.mobile} bind:value />
|
||||
<Range
|
||||
on:change={onSwipeChange}
|
||||
min={20}
|
||||
max={90}
|
||||
disabled={!$settings.mobile}
|
||||
bind:value={swipeThresholdValue}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label>Edge button width</Label>
|
||||
<Range on:change={onWidthChange} min={1} max={100} bind:value={edgeButtonWidthValue} />
|
||||
</div>
|
||||
</div>
|
||||
</AccordionItem>
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
{ key: 'pageNum', text: 'Show page number', value: $settings.pageNum },
|
||||
{ key: 'charCount', text: 'Show character count', value: $settings.charCount },
|
||||
{ key: 'mobile', text: 'Mobile', value: $settings.mobile },
|
||||
{ key: 'showTimer', text: 'Show timer', value: $settings.showTimer }
|
||||
{ key: 'showTimer', text: 'Show timer', value: $settings.showTimer },
|
||||
{ key: 'quickActions', text: 'Show quick actions', value: $settings.quickActions }
|
||||
] as { key: SettingsKey; text: string; value: any }[];
|
||||
</script>
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
import VolumeSettings from './Volume/VolumeSettings.svelte';
|
||||
import About from './About.svelte';
|
||||
import QuickAccess from './QuickAccess.svelte';
|
||||
import { beforeNavigate } from '$app/navigation';
|
||||
|
||||
let transitionParams = {
|
||||
x: 320,
|
||||
@@ -30,6 +31,13 @@
|
||||
function onClose() {
|
||||
hidden = true;
|
||||
}
|
||||
|
||||
beforeNavigate((nav) => {
|
||||
if (!hidden) {
|
||||
nav.cancel();
|
||||
hidden = true;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<Drawer
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
import { AccordionItem, Helper, Toggle } from 'flowbite-svelte';
|
||||
|
||||
$: toggles = [
|
||||
{ key: 'rightToLeft', text: 'Right to left', value: $settings.volumeDefaults.rightToLeft },
|
||||
{ key: 'rightToLeft', text: 'Right to left', value: $settings.volumeDefaults?.rightToLeft },
|
||||
{
|
||||
key: 'singlePageView',
|
||||
text: 'Single page view',
|
||||
value: $settings.volumeDefaults.singlePageView
|
||||
value: $settings.volumeDefaults?.singlePageView
|
||||
},
|
||||
{ key: 'hasCover', text: 'First page is cover', value: $settings.volumeDefaults.hasCover }
|
||||
{ key: 'hasCover', text: 'First page is cover', value: $settings.volumeDefaults?.hasCover }
|
||||
] as { key: VolumeDefaultsKey; text: string; value: any }[];
|
||||
</script>
|
||||
|
||||
|
||||
@@ -49,7 +49,9 @@ export type Settings = {
|
||||
mobile: boolean;
|
||||
backgroundColor: string;
|
||||
swipeThreshold: number;
|
||||
edgeButtonWidth: number;
|
||||
showTimer: boolean;
|
||||
quickActions: boolean;
|
||||
fontSize: FontSize;
|
||||
zoomDefault: ZoomModes;
|
||||
volumeDefaults: VolumeDefaults;
|
||||
@@ -72,7 +74,9 @@ const defaultSettings: Settings = {
|
||||
mobile: false,
|
||||
backgroundColor: '#030712',
|
||||
swipeThreshold: 50,
|
||||
edgeButtonWidth: 10,
|
||||
showTimer: false,
|
||||
quickActions: true,
|
||||
fontSize: 'auto',
|
||||
zoomDefault: 'zoomFitToScreen',
|
||||
volumeDefaults: {
|
||||
|
||||
Reference in New Issue
Block a user