Skip to content

Commit 7ae1194

Browse files
committed
add image occlusion page
add side toolbar, top toolbar, mask editor and note editor - option to switch between mask editor and note editor
1 parent 1b50f8c commit 7ae1194

File tree

4 files changed

+173
-0
lines changed

4 files changed

+173
-0
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<!--
2+
Copyright: Ankitects Pty Ltd and contributors
3+
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
4+
-->
5+
<script lang="ts">
6+
import * as tr from "@tslib/ftl";
7+
8+
import Container from "../components/Container.svelte";
9+
import type { Decks } from "../lib/proto";
10+
import { saveImageNotes } from "./generate";
11+
import MasksEditor from "./MaskEditor.svelte";
12+
import Notes from "./Notes.svelte";
13+
import StickyFooter from "./StickyFooter.svelte";
14+
15+
export let path: string;
16+
export let deckNameIds: Decks.DeckNameId[];
17+
export let deckId: number | null;
18+
19+
async function hideAllGuessOne(): Promise<void> {
20+
saveImageNotes(path, deckId!, true);
21+
}
22+
23+
async function hideOneGuessOne(): Promise<void> {
24+
saveImageNotes(path, deckId!, false);
25+
}
26+
27+
const items = [
28+
{ label: tr.notetypesOcclusionMask(), value: 1 },
29+
{ label: tr.notetypesOcclusionNote(), value: 2 },
30+
];
31+
32+
let activeTabValue = 1;
33+
const tabChange = (tabValue) => () => (activeTabValue = tabValue);
34+
</script>
35+
36+
<Container class="image-occlusion">
37+
<ul>
38+
{#each items as item}
39+
<li class={activeTabValue === item.value ? "active" : ""}>
40+
<span on:click={tabChange(item.value)}>{item.label}</span>
41+
</li>
42+
{/each}
43+
</ul>
44+
45+
<div hidden={activeTabValue != 1}>
46+
<MasksEditor {path} />
47+
</div>
48+
49+
<div hidden={activeTabValue != 2}>
50+
<Notes {deckNameIds} bind:deckId />
51+
<StickyFooter {hideAllGuessOne} {hideOneGuessOne} />
52+
</div>
53+
</Container>
54+
55+
<style lang="scss">
56+
:global(.image-occlusion) {
57+
--gutter-inline: 0.5rem;
58+
59+
:global(.row) {
60+
// rows have negative margins by default
61+
--bs-gutter-x: 0;
62+
// ensure equal spacing between tall rows like
63+
// dropdowns, and short rows like checkboxes
64+
min-height: 2.5em;
65+
align-items: center;
66+
}
67+
}
68+
ul {
69+
display: flex;
70+
flex-wrap: wrap;
71+
padding-left: 0;
72+
list-style: none;
73+
border-bottom: 1px solid #dee2e6;
74+
}
75+
li {
76+
margin-bottom: -1px;
77+
}
78+
79+
span {
80+
border: 1px solid transparent;
81+
border-top-left-radius: 0.25rem;
82+
border-top-right-radius: 0.25rem;
83+
display: block;
84+
padding: 0.5rem 1rem;
85+
cursor: pointer;
86+
}
87+
88+
span:hover {
89+
border-color: #e9ecef #e9ecef #dee2e6;
90+
}
91+
92+
li.active > span {
93+
color: #495057;
94+
background-color: #fff;
95+
border-color: #dee2e6 #dee2e6 #fff;
96+
}
97+
</style>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
@use "sass/vars";
2+
@use "sass/bootstrap-dark";
3+
4+
@import "sass/base";
5+
6+
@import "bootstrap/scss/alert";
7+
@import "bootstrap/scss/buttons";
8+
@import "bootstrap/scss/button-group";
9+
@import "bootstrap/scss/close";
10+
@import "bootstrap/scss/grid";
11+
@import "sass/bootstrap-forms";
12+
13+
.night-mode {
14+
@include bootstrap-dark.night-mode;
15+
}
16+
17+
body {
18+
width: min(100vw, 70em);
19+
margin: 6px auto;
20+
// padding: 1em;
21+
// pad out the underside of the footer
22+
padding-bottom: 5em;
23+
}
24+
25+
html {
26+
overflow: hidden;
27+
}

ts/image-occlusion/index.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright: Ankitects Pty Ltd and contributors
2+
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
3+
4+
import "./image-occlusion-base.scss";
5+
6+
import { ModuleName, setupI18n } from "@tslib/i18n";
7+
8+
import { checkNightMode } from "../lib/nightmode";
9+
import { Decks, decks as decksService } from "../lib/proto";
10+
import ImageOcclusionPage from "./ImageOcclusionPage.svelte";
11+
import { getImageClozeMetadata } from "./lib";
12+
13+
const i18n = setupI18n({
14+
modules: [
15+
ModuleName.IMPORTING,
16+
ModuleName.DECKS,
17+
ModuleName.EDITING,
18+
ModuleName.NOTETYPES,
19+
],
20+
});
21+
22+
const gettingDecks = decksService.getDeckNames(
23+
Decks.GetDeckNamesRequest.create({
24+
skipEmptyDefault: false,
25+
includeFiltered: false,
26+
}),
27+
);
28+
29+
export async function setupImageOcclusion(path: string): Promise<ImageOcclusionPage> {
30+
checkNightMode();
31+
32+
const gettingmetadata = getImageClozeMetadata(path);
33+
const [metadata, decks] = await Promise.all([gettingmetadata, gettingDecks, i18n]);
34+
35+
return new ImageOcclusionPage({
36+
target: document.body,
37+
props: {
38+
path: path,
39+
deckNameIds: decks.entries,
40+
deckId: metadata.deckId ? metadata.deckId : null,
41+
},
42+
});
43+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Copyright: Ankitects Pty Ltd and contributors
2+
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
3+
4+
import NotesToolbar from "./NotesToolbar.svelte";
5+
6+
export default NotesToolbar;

0 commit comments

Comments
 (0)