Compare commits
3 commits
2b5a19fdd6
...
d6c5e52527
Author | SHA1 | Date | |
---|---|---|---|
d6c5e52527 | |||
5740d173c5 | |||
9a8f2198f1 |
13 changed files with 505 additions and 96 deletions
src-tauri
src
44
src-tauri/Cargo.lock
generated
44
src-tauri/Cargo.lock
generated
|
@ -347,10 +347,14 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "comicinfo-editor-v2"
|
name = "comicinfo-editor-v2"
|
||||||
version = "0.0.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"quick-xml",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde-xml-rs",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"strum",
|
||||||
|
"strum_macros",
|
||||||
"tauri",
|
"tauri",
|
||||||
"tauri-build",
|
"tauri-build",
|
||||||
]
|
]
|
||||||
|
@ -1996,6 +2000,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "81b9228215d82c7b61490fec1de287136b5de6f5700f6e58ea9ad61a7964ca51"
|
checksum = "81b9228215d82c7b61490fec1de287136b5de6f5700f6e58ea9ad61a7964ca51"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2272,6 +2277,18 @@ dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde-xml-rs"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fb3aa78ecda1ebc9ec9847d5d3aba7d618823446a049ba2491940506da6e2782"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"serde",
|
||||||
|
"thiserror",
|
||||||
|
"xml-rs",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.188"
|
version = "1.0.188"
|
||||||
|
@ -2497,6 +2514,25 @@ version = "0.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum"
|
||||||
|
version = "0.25.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum_macros"
|
||||||
|
version = "0.25.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0"
|
||||||
|
dependencies = [
|
||||||
|
"heck 0.4.1",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rustversion",
|
||||||
|
"syn 2.0.38",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.109"
|
version = "1.0.109"
|
||||||
|
@ -3651,3 +3687,9 @@ checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "xml-rs"
|
||||||
|
version = "0.8.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a"
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
[package]
|
[package]
|
||||||
name = "comicinfo-editor-v2"
|
name = "comicinfo-editor-v2"
|
||||||
version = "0.0.0"
|
version = "0.1.0"
|
||||||
description = "A Tauri App"
|
description = "App for creating Comicinfo.xml files"
|
||||||
authors = ["you"]
|
authors = ["Neshura"]
|
||||||
license = ""
|
license = ""
|
||||||
repository = ""
|
repository = ""
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
@ -14,8 +14,12 @@ tauri-build = { version = "1.4", features = [] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tauri = { version = "1.4", features = ["shell-open"] }
|
tauri = { version = "1.4", features = ["shell-open"] }
|
||||||
|
quick-xml = { version = "0.29.0", features = ["serde", "serialize"] }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde-xml-rs = "0.6.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
strum = "0.25.0"
|
||||||
|
strum_macros = "0.25.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# this feature is used for production builds or when `devPath` points to the filesystem
|
# this feature is used for production builds or when `devPath` points to the filesystem
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::metadata::{*};
|
||||||
|
mod metadata;
|
||||||
|
|
||||||
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
|
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn greet(name: &str) -> String {
|
fn greet(name: &str) -> String {
|
||||||
|
@ -9,7 +14,13 @@ fn greet(name: &str) -> String {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.invoke_handler(tauri::generate_handler![greet])
|
.invoke_handler(tauri::generate_handler![greet, test])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
fn test(message: metadata::Metadata) -> String {
|
||||||
|
message.save_to_xml("/home/neshura/Repositories/comicinfo-editor-v2/ComicInfo.xml");
|
||||||
|
format!("Series: '{}' | Title: '{}'", message.series_title, message.title)
|
||||||
|
}
|
||||||
|
|
206
src-tauri/src/metadata/mod.rs
Normal file
206
src-tauri/src/metadata/mod.rs
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
use std::{fs::File, io::{Write, Cursor}};
|
||||||
|
use quick_xml::{se::Serializer, events::BytesStart};
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
use serde::ser::{SerializeSeq, SerializeStruct};
|
||||||
|
|
||||||
|
use serde_xml_rs::{to_string, to_writer};
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, PartialEq, Clone)]
|
||||||
|
pub(crate) struct Metadata {
|
||||||
|
pub(crate) title: String,
|
||||||
|
pub(crate) series_title: String,
|
||||||
|
|
||||||
|
pub(crate) chapter_number: u16,
|
||||||
|
|
||||||
|
pub(crate) total_chapter_count: i16,
|
||||||
|
|
||||||
|
pub(crate) volume_number: i16,
|
||||||
|
|
||||||
|
pub(crate) summary: String,
|
||||||
|
|
||||||
|
pub(crate) release_date: ReleaseDate,
|
||||||
|
|
||||||
|
pub(crate) writer: String,
|
||||||
|
pub(crate) translator: String,
|
||||||
|
pub(crate) letterer: String,
|
||||||
|
pub(crate) editor: String,
|
||||||
|
|
||||||
|
pub(crate) publisher: String,
|
||||||
|
|
||||||
|
pub(crate) genre: String,
|
||||||
|
|
||||||
|
pub(crate) tags: Vec<String>,
|
||||||
|
|
||||||
|
pub(crate) page_count: u16,
|
||||||
|
|
||||||
|
pub(crate) language: String,
|
||||||
|
|
||||||
|
pub(crate) characters: Vec<String>,
|
||||||
|
|
||||||
|
pub(crate) age_rating: String
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Metadata {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
title: "".into(),
|
||||||
|
series_title: "".into(),
|
||||||
|
chapter_number: 0,
|
||||||
|
total_chapter_count: -1,
|
||||||
|
volume_number: 1,
|
||||||
|
summary: "".into(),
|
||||||
|
release_date: ReleaseDate {
|
||||||
|
year: -1,
|
||||||
|
month: -1,
|
||||||
|
day: -1,
|
||||||
|
},
|
||||||
|
writer: "".into(),
|
||||||
|
letterer: "".into(),
|
||||||
|
editor: "".into(),
|
||||||
|
translator: "".into(),
|
||||||
|
publisher: "".into(),
|
||||||
|
genre: "".into(),
|
||||||
|
tags: vec![],
|
||||||
|
page_count: 0,
|
||||||
|
language: "en".into(),
|
||||||
|
characters: vec![],
|
||||||
|
age_rating: "Unknown".into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for Metadata {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer {
|
||||||
|
let mut out_state = serializer.serialize_struct("Metadata", 22)?;
|
||||||
|
out_state.serialize_field("@xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")?;
|
||||||
|
out_state.serialize_field("@xsi:noNamespaceSchemaLocation", "ComicInfo.xsd")?;
|
||||||
|
out_state.serialize_field("Series", &self.series_title)?;
|
||||||
|
out_state.serialize_field("Title", &self.title)?;
|
||||||
|
|
||||||
|
out_state.serialize_field("Number", &self.chapter_number)?;
|
||||||
|
out_state.serialize_field("Count", &self.total_chapter_count)?;
|
||||||
|
out_state.serialize_field("Volume", &self.volume_number)?;
|
||||||
|
|
||||||
|
if self.summary != "" {
|
||||||
|
out_state.serialize_field("Summary", &self.summary)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_state.serialize_field("Year", &self.release_date.year)?;
|
||||||
|
out_state.serialize_field("Month", &self.release_date.month)?;
|
||||||
|
out_state.serialize_field("Day", &self.release_date.day)?;
|
||||||
|
|
||||||
|
if self.writer != "" {
|
||||||
|
out_state.serialize_field("Writer", &self.writer)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.letterer != "" {
|
||||||
|
out_state.serialize_field("Letterer", &self.letterer)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.editor != "" {
|
||||||
|
out_state.serialize_field("Editor", &self.editor)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.translator != "" {
|
||||||
|
out_state.serialize_field("Translator", &self.translator)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.publisher != "" {
|
||||||
|
out_state.serialize_field("Publisher", &self.publisher)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_state.serialize_field("Genre", &self.genre)?;
|
||||||
|
|
||||||
|
if self.tags.len() != 0 {
|
||||||
|
out_state.serialize_field("Tags", &self.tags.join(", "))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_state.serialize_field("PageCount", &self.page_count)?;
|
||||||
|
|
||||||
|
out_state.serialize_field("LanguageISO", &self.language)?;
|
||||||
|
|
||||||
|
if self.characters.len() != 0 {
|
||||||
|
out_state.serialize_field("Characters", &self.characters.join(", "))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_state.serialize_field("AgeRating", &self.age_rating)?;
|
||||||
|
|
||||||
|
out_state.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Metadata {
|
||||||
|
pub(crate) fn save_to_xml(&self, path: &str) {
|
||||||
|
let mut file = File::create(path).unwrap();
|
||||||
|
let mut buffer = String::new();
|
||||||
|
let root = "ComicInfo";
|
||||||
|
|
||||||
|
let mut ser = Serializer::with_root(&mut buffer, Some(root)).unwrap();
|
||||||
|
ser.indent(' ', 4);
|
||||||
|
|
||||||
|
self.serialize(ser).unwrap();
|
||||||
|
file.write(buffer.as_bytes()).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, PartialEq, Clone)]
|
||||||
|
pub(crate) struct ReleaseDate {
|
||||||
|
year: i16,
|
||||||
|
month: i8,
|
||||||
|
day: i8
|
||||||
|
}
|
||||||
|
|
||||||
|
/*#[derive(strum_macros::Display, Debug, PartialEq, strum_macros::EnumIter, Serialize, Deserialize, Clone)]
|
||||||
|
#[serde(tag = "AgeRating")]
|
||||||
|
pub(crate) enum AgeRating {
|
||||||
|
#[strum(serialize="Unknown")]
|
||||||
|
Unknown,
|
||||||
|
#[strum(serialize="Adults Only 18+")]
|
||||||
|
#[serde(rename="Adults Only 18+")]
|
||||||
|
AdultsOnly,
|
||||||
|
#[strum(serialize="Early Childhood")]
|
||||||
|
#[serde(rename="Early Childhood")]
|
||||||
|
EarlyChildhood,
|
||||||
|
#[strum(serialize="Everyone")]
|
||||||
|
Everyone,
|
||||||
|
#[strum(serialize="Everyone 10+")]
|
||||||
|
#[serde(rename="Everyone 10+")]
|
||||||
|
Everyone10,
|
||||||
|
#[strum(serialize="G")]
|
||||||
|
G,
|
||||||
|
#[strum(serialize="Kids to Adults")]
|
||||||
|
#[serde(rename="Kids to Adults")]
|
||||||
|
KidsAdults,
|
||||||
|
#[strum(serialize="M")]
|
||||||
|
M,
|
||||||
|
#[strum(serialize="MA15+")]
|
||||||
|
#[serde(rename="MA15+")]
|
||||||
|
MA15,
|
||||||
|
#[strum(serialize="Mature 17+")]
|
||||||
|
#[serde(rename="Mature 17+")]
|
||||||
|
Mature,
|
||||||
|
#[strum(serialize="PG")]
|
||||||
|
PG,
|
||||||
|
#[strum(serialize="R18+")]
|
||||||
|
#[serde(rename="R18+")]
|
||||||
|
R18,
|
||||||
|
#[strum(serialize="Rating Pending")]
|
||||||
|
#[serde(rename="Rating Pending")]
|
||||||
|
RatingPending,
|
||||||
|
#[strum(serialize="Teen")]
|
||||||
|
Teen,
|
||||||
|
#[strum(serialize="X18+")]
|
||||||
|
#[serde(rename="X18+")]
|
||||||
|
X18
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(strum_macros::Display, Debug, PartialEq, strum_macros::EnumIter, Serialize, Deserialize, Clone)]
|
||||||
|
#[serde(tag = "LanguageISO")]
|
||||||
|
pub(crate) enum LanguageISO {
|
||||||
|
#[strum(serialize="en")]
|
||||||
|
#[serde(rename="en")]
|
||||||
|
EN,
|
||||||
|
#[strum(serialize="jp")]
|
||||||
|
#[serde(rename="jp")]
|
||||||
|
JP
|
||||||
|
}*/
|
|
@ -8,7 +8,7 @@
|
||||||
},
|
},
|
||||||
"package": {
|
"package": {
|
||||||
"productName": "comicinfo-editor-v2",
|
"productName": "comicinfo-editor-v2",
|
||||||
"version": "0.0.0"
|
"version": "0.1.0"
|
||||||
},
|
},
|
||||||
"tauri": {
|
"tauri": {
|
||||||
"allowlist": {
|
"allowlist": {
|
||||||
|
|
|
@ -22,9 +22,6 @@
|
||||||
Settings go here
|
Settings go here
|
||||||
</p>
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="row">
|
|
||||||
<Greet />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
48
src/lib/Dropdown/Dropdown.svelte
Normal file
48
src/lib/Dropdown/Dropdown.svelte
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<script lang="ts">
|
||||||
|
let open = false;
|
||||||
|
|
||||||
|
export let list: Array<string>;
|
||||||
|
export let activeElement: string;
|
||||||
|
export let id: string;
|
||||||
|
|
||||||
|
function handleDropdownOpen() {
|
||||||
|
open = !open;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSelect(newSelection: string) {
|
||||||
|
console.log("newSelection")
|
||||||
|
activeElement = newSelection;
|
||||||
|
open = false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div {id} class="dropdown-container">
|
||||||
|
<button on:click|preventDefault={handleDropdownOpen}>{activeElement}</button>
|
||||||
|
|
||||||
|
{#if open}
|
||||||
|
<div class="dropdown-list">
|
||||||
|
{#each list as listElem}
|
||||||
|
<div class="dropdown-element" on:click|preventDefault={() => {handleSelect(listElem)}}>{listElem}</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.dropdown-container {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-list {
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
max-height: 10rem;
|
||||||
|
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
z-index: 100;
|
||||||
|
|
||||||
|
background-color: var(--color-bg);
|
||||||
|
border: 1px solid var(--color-border)
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -13,10 +13,6 @@
|
||||||
function inputInteger(event: Event & {currentTarget: (EventTarget & HTMLInputElement)}) {
|
function inputInteger(event: Event & {currentTarget: (EventTarget & HTMLInputElement)}) {
|
||||||
let newValue = event.currentTarget.value;
|
let newValue = event.currentTarget.value;
|
||||||
|
|
||||||
if (newValue.startsWith("0") && newValue.length > 1) {
|
|
||||||
newValue = newValue.slice(1, newValue.length)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newValue != "" && !isNaN(Number(newValue))) {
|
if (newValue != "" && !isNaN(Number(newValue))) {
|
||||||
value = Number(newValue);
|
value = Number(newValue);
|
||||||
}
|
}
|
||||||
|
@ -25,17 +21,13 @@
|
||||||
event.currentTarget.value = value.toString();
|
event.currentTarget.value = value.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (newValue === "") {
|
|
||||||
event.currentTarget.value = defaultValue.toString();
|
|
||||||
value = defaultValue;
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
event.currentTarget.value = value.toString();
|
event.currentTarget.value = value.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<input {id} type="text" class="digitInput" style="--valuelen: {value.toString().length + 3}ch" on:input|preventDefault={inputInteger} {value}>
|
<input {id} type="number" class="digitInput" style="--valuelen: {value.toString().length + 4}ch" on:input|preventDefault={inputInteger} {value}>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.digitInput {
|
.digitInput {
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<input id="tag-{id}" type="text" class="letterInput" style="--valuelen: {width}ch" bind:value={value}>
|
<input id="tag-{id}" type="text" class="letterInput" style="--valuelen: {width}ch" bind:value={value}>
|
||||||
<button on:click={handleClick}>X</button>
|
<button on:click|preventDefault={handleClick}>X</button>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.letterInput {
|
.letterInput {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button {id} class="letterInput" on:click={handleClick}>+</button>
|
<button {id} class="letterInput" on:click|preventDefault={handleClick}>+</button>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.letterInput {
|
.letterInput {
|
||||||
|
|
|
@ -1,125 +1,166 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {writable} from "svelte/store";
|
|
||||||
import type {Writable} from "svelte/store";
|
|
||||||
import IntegerInput from "./IntegerInput.svelte";
|
import IntegerInput from "./IntegerInput.svelte";
|
||||||
import TextInput from "./TextInput.svelte";
|
import TextInput from "./TextInput.svelte";
|
||||||
import NewListTextInput from "./ListTextInput/NewListTextInput.svelte";
|
import NewListTextInput from "./ListTextInput/NewListTextInput.svelte";
|
||||||
import ListTextInputElement from "./ListTextInput/ListTextInputElement.svelte";
|
import ListTextInputElement from "./ListTextInput/ListTextInputElement.svelte";
|
||||||
|
import {invoke} from "@tauri-apps/api/tauri";
|
||||||
|
import {AgeRating, LanguageISO, type Metadata} from "./metadata";
|
||||||
|
import Dropdown from "./Dropdown/Dropdown.svelte";
|
||||||
|
|
||||||
let seriesTitle = "";
|
let returnMessage = "";
|
||||||
let volumeTitle = "";
|
|
||||||
let volumeNumber = 0;
|
let metadata: Metadata = {
|
||||||
let chapterNumber = 0;
|
series_title: "",
|
||||||
let pageCount = 1;
|
title: "",
|
||||||
let chapterCount = 0;
|
|
||||||
let summary = "";
|
chapter_number: 0,
|
||||||
let releaseYear: number;
|
|
||||||
let releaseMonth: number;
|
total_chapter_count: -1,
|
||||||
let releaseDay: number;
|
|
||||||
let author: string;
|
volume_number: -1,
|
||||||
let typesetter: string;
|
|
||||||
let editor: string;
|
summary: "",
|
||||||
let translator: string;
|
|
||||||
let publisher: string;
|
release_date: {
|
||||||
let tags: Array<string> = [];
|
year: new Date().getFullYear(),
|
||||||
let genre = "Hentai";
|
month: -1,
|
||||||
let lang = "en";
|
day: -1,
|
||||||
let ageRating = "18+";
|
},
|
||||||
|
|
||||||
|
writer: "",
|
||||||
|
translator: "",
|
||||||
|
letterer: "",
|
||||||
|
editor: "",
|
||||||
|
|
||||||
|
publisher: "",
|
||||||
|
|
||||||
|
genre: "",
|
||||||
|
|
||||||
|
tags: [],
|
||||||
|
|
||||||
|
page_count: 1,
|
||||||
|
|
||||||
|
language: LanguageISO.EN,
|
||||||
|
|
||||||
|
characters: [],
|
||||||
|
|
||||||
|
age_rating: AgeRating.Unknown
|
||||||
|
};
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
if (releaseYear < 0) {
|
if (metadata.release_date.year < 0) {
|
||||||
releaseMonth = -1;
|
metadata.release_date.month = -1;
|
||||||
}
|
}
|
||||||
if (releaseMonth < 0) {
|
if (metadata.release_date.month < 0) {
|
||||||
releaseDay = -1;
|
metadata.release_date.day = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteTag(event: any) {
|
function deleteTag(event: any) {
|
||||||
console.log("deleted")
|
metadata.tags.splice(event.detail.tagId, 1);
|
||||||
tags.splice(event.detail.tagId, 1);
|
metadata.tags = metadata.tags;
|
||||||
tags = tags;
|
}
|
||||||
|
|
||||||
|
async function saveMetadata() {
|
||||||
|
console.log(metadata);
|
||||||
|
returnMessage = await invoke("test", { message: metadata })
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="metadataInput">
|
<div class="metadataInputContainer">
|
||||||
<h1>Metadata</h1>
|
<h1>Metadata</h1>
|
||||||
|
|
||||||
<label for="series">Series:</label>
|
<form class="metadataInput" on:submit|preventDefault={saveMetadata}>
|
||||||
<TextInput id="series" bind:value={seriesTitle} placeholder="Series Title" /><br>
|
|
||||||
|
|
||||||
<label for="title">Title:</label>
|
|
||||||
<TextInput id="title" bind:value={volumeTitle} placeholder="Volume Title" /><br>
|
|
||||||
|
|
||||||
<label for="volume">Volume:</label>
|
<label for="series">Series:</label>
|
||||||
<IntegerInput id="volume" bind:value={volumeNumber} />
|
<TextInput id="series" bind:value={metadata.series_title} placeholder="Series Title" /><br>
|
||||||
<label for="chapter">Chapter:</label>
|
|
||||||
<IntegerInput id="chapter" bind:value={chapterNumber} /> /
|
|
||||||
|
|
||||||
<IntegerInput id="chapter_count" bind:value={chapterCount} negative={true}/><br>
|
<label for="title">Title:</label>
|
||||||
|
<TextInput id="title" bind:value={metadata.title} placeholder="Volume Title" /><br>
|
||||||
|
|
||||||
<label for="page_count">Page Count</label>
|
<label for="volume">Volume:</label>
|
||||||
<IntegerInput id="page_count" bind:value={pageCount} defaultValue={1} /><br>
|
<IntegerInput id="volume" bind:value={metadata.volume_number} defaultValue={-1}/>
|
||||||
|
<label for="chapter">Chapter:</label>
|
||||||
|
<IntegerInput id="chapter" bind:value={metadata.chapter_number} /> /
|
||||||
|
|
||||||
<label for="summary">Summary:</label><br>
|
<IntegerInput id="chapter_count" bind:value={metadata.total_chapter_count} negative={true}/><br>
|
||||||
<label for="summary"></label><input id="series" type="text"><br>
|
|
||||||
|
|
||||||
<label for="release_date">Release Date:</label>
|
<label for="page_count">Page Count</label>
|
||||||
<IntegerInput id="release_year" bind:value={releaseYear} defaultValue={new Date().getFullYear()} />
|
<IntegerInput id="page_count" bind:value={metadata.page_count} /><br>
|
||||||
{#if releaseYear > 0}
|
|
||||||
<IntegerInput id="release_month" bind:value={releaseMonth} defaultValue={new Date().getMonth()} />
|
<label for="summary">Summary:</label><br>
|
||||||
{#if releaseMonth > 0}
|
<label for="summary"></label><textarea rows="3" cols="60" id="series" name="text" placeholder="Summary..." bind:value={metadata.summary}></textarea><br>
|
||||||
<IntegerInput id="release_day" bind:value={releaseDay} defaultValue={new Date().getDay()} />
|
|
||||||
|
<label for="release_date">Release Date:</label>
|
||||||
|
<IntegerInput id="release_year" bind:value={metadata.release_date.year} />
|
||||||
|
{#if metadata.release_date.year > 0}
|
||||||
|
<IntegerInput id="release_month" bind:value={metadata.release_date.month} />
|
||||||
|
{#if metadata.release_date.month > 0}
|
||||||
|
<IntegerInput id="release_day" bind:value={metadata.release_date.day} />
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
<br>
|
||||||
<br>
|
<!--TODO: if date element is 0 do not display finer element, also set finer element to -1-->
|
||||||
<!--TODO: if date element is 0 do not display finer element, also set finer element to -1-->
|
|
||||||
|
|
||||||
<label for="author">Author:</label>
|
<label for="author">Author:</label>
|
||||||
<TextInput id="author" bind:value={author} placeholder="Author" /><br>
|
<TextInput id="author" bind:value={metadata.writer} placeholder="Author" /><br>
|
||||||
|
|
||||||
<label for="typesetter">Typesetter:</label>
|
<label for="translator">Translator:</label>
|
||||||
<TextInput id="typesetter" bind:value={typesetter} placeholder="Typesetter" /><br>
|
<TextInput id="translator" bind:value={metadata.translator} placeholder="Translator" /><br>
|
||||||
|
|
||||||
<label for="editor">Editor:</label>
|
<label for="typesetter">Letterer:</label>
|
||||||
<TextInput id="editor" bind:value={editor} placeholder="Editor" /><br>
|
<TextInput id="typesetter" bind:value={metadata.letterer} placeholder="Letterer" /><br>
|
||||||
|
|
||||||
<label for="translator">Translator:</label>
|
<label for="editor">Editor:</label>
|
||||||
<TextInput id="translator" bind:value={translator} placeholder="Translator" /><br>
|
<TextInput id="editor" bind:value={metadata.editor} placeholder="Editor" /><br>
|
||||||
|
|
||||||
<label for="publisher">Publisher:</label>
|
<label for="publisher">Publisher:</label>
|
||||||
<TextInput id="publisher" bind:value={publisher} placeholder="Publisher" /><br>
|
<TextInput id="publisher" bind:value={metadata.publisher} placeholder="Publisher" /><br>
|
||||||
|
|
||||||
<label for="new-tag">Tags:</label>
|
<label for="new-tag">Tags:</label>
|
||||||
<!-- List of Tags, New Button -->
|
<!-- List of Tags, New Button -->
|
||||||
{#each tags as tag, id}
|
{#each metadata.tags as tag, id}
|
||||||
<ListTextInputElement {id} bind:value={tag} on:deleted={deleteTag}/>
|
<ListTextInputElement {id} bind:value={tag} on:deleted={deleteTag}/>
|
||||||
{/each}
|
{/each}
|
||||||
<NewListTextInput id="new-tag" bind:value={tags[tags.length]}/><br>
|
<NewListTextInput id="new-tag" bind:value={metadata.tags[metadata.tags.length]}/><br>
|
||||||
|
|
||||||
<label for="genre">Genre</label>
|
|
||||||
<TextInput id="genre" bind:value={genre} placeholder="Genre" />
|
|
||||||
|
|
||||||
<label for="lang">Language</label>
|
<div class="row-left">
|
||||||
<input id="lang" type="text"><br>
|
<label for="genre">Genre:</label>
|
||||||
|
<TextInput id="genre" bind:value={metadata.genre} placeholder="Genre" />
|
||||||
|
|
||||||
<label for="age_rating">Age Rating</label>
|
<label for="language-select">Language:</label>
|
||||||
<input id="age_rating" type="text"><br>
|
<Dropdown id="language-select" bind:activeElement={metadata.language} list={Object.values(LanguageISO)}></Dropdown>
|
||||||
|
</div>
|
||||||
|
|
||||||
<input type="submit" value="Save"/>
|
<div class="row-left">
|
||||||
|
<label for="age-rating">Age Rating:</label>
|
||||||
|
<Dropdown id="" bind:activeElement={metadata.age_rating} list={Object.values(AgeRating)}></Dropdown>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input type="submit" value="Save"/>
|
||||||
|
<p>{returnMessage}</p>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.metadataInput {
|
.metadataInputContainer {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.metadataInput label, input[type="submit"] {
|
.metadataInput {
|
||||||
margin-left: 4rem;
|
margin-left: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.metadataInput label, input[type="submit"] {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
.metadataInput h1 {
|
.metadataInput h1 {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|
62
src/lib/metadata.ts
Normal file
62
src/lib/metadata.ts
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
type Metadata = {
|
||||||
|
title: string,
|
||||||
|
series_title: string,
|
||||||
|
|
||||||
|
chapter_number: number,
|
||||||
|
total_chapter_count: number,
|
||||||
|
volume_number: number,
|
||||||
|
|
||||||
|
summary: string,
|
||||||
|
|
||||||
|
release_date: ReleaseDate,
|
||||||
|
|
||||||
|
writer: string,
|
||||||
|
translator: string,
|
||||||
|
letterer: string
|
||||||
|
editor: string,
|
||||||
|
|
||||||
|
publisher: string,
|
||||||
|
|
||||||
|
genre: string,
|
||||||
|
|
||||||
|
tags: string[],
|
||||||
|
|
||||||
|
page_count: number,
|
||||||
|
|
||||||
|
language: LanguageISO,
|
||||||
|
|
||||||
|
characters: string[]
|
||||||
|
|
||||||
|
age_rating: AgeRating
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReleaseDate = {
|
||||||
|
year: number,
|
||||||
|
month: number,
|
||||||
|
day: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum AgeRating {
|
||||||
|
Unknown = "Unknown",
|
||||||
|
AdultsOnly = "Adults Only 18+",
|
||||||
|
EarlyChildhood = "Early Childhood",
|
||||||
|
Everyone = "Everyone",
|
||||||
|
Everyone10 = "Everyone 10+",
|
||||||
|
G = "G",
|
||||||
|
KidsAdults = "Kids to Adults",
|
||||||
|
M = "M",
|
||||||
|
MA15 = "MA15+",
|
||||||
|
Mature = "Mature 17+",
|
||||||
|
PG = "PG",
|
||||||
|
R18 = "R18+",
|
||||||
|
RatingPending = "Rating Pending",
|
||||||
|
X18 = "X18+"
|
||||||
|
}
|
||||||
|
|
||||||
|
enum LanguageISO {
|
||||||
|
EN = "en",
|
||||||
|
JP = "jp"
|
||||||
|
}
|
||||||
|
|
||||||
|
export { LanguageISO, AgeRating}
|
||||||
|
export type {Metadata, ReleaseDate}
|
|
@ -5,6 +5,7 @@
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|
||||||
--color-bg: #f6f6f6;
|
--color-bg: #f6f6f6;
|
||||||
|
--color-border: #000000;
|
||||||
|
|
||||||
color: #0f0f0f;
|
color: #0f0f0f;
|
||||||
background-color: #f6f6f6;
|
background-color: #f6f6f6;
|
||||||
|
@ -58,6 +59,11 @@ body, html {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.row-left {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #646cff;
|
color: #646cff;
|
||||||
|
|
Reference in a new issue